Displaying "Hello World" Image on a new window

Aug 5, 2010 at 1:44 AM

Hi
I am taking the Hello World sample and extending to learn a few additional things like integration of opencv+emgu for WPF app

What I want to accomplish:
In the Hello World sample, when the user types in some text in the textbox and presses the "Click Me" button, I want to open a new Window and show an  Image of the text typed.  I am not really sure how to accomplish this.

What I have so far:
(1) DisplayMessageView.xaml

<Window x:Class="Caliburn.Micro.EmguHello.DisplayMessageView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="303" Width="564">
    <Grid>
        <Image x:Name="image1" Stretch="Fill" />
    </Grid>
</Window>

(2) DisplayMessageViewModel.cs

namespace Caliburn.Micro.EmguHello
{
    public class DisplayMessageViewModel : PropertyChangedBase
    {
        string textname;
        public string Textname
        {
            get { return textname; }
            set
            {
                textname = value;
            }
        }

        Image image1;
        public Image Image1 { get; set; }

        // Question: How do I get this called?
        public void Image1Initialized()
        {
            string displayString = string.Format("Hello Emgu {0}!", Textname);
            Image<Bgr, Byte> image = new Image<Bgr, byte>(400, 100, new Bgr(255, 255, 255));
            MCvFont f = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 3.0, 3.0);
            image.Draw(displayString, ref f, new System.Drawing.Point(10, 50), new Bgr(255.0, 0.0, 0.0));

            image1.Source = ToBitmapSource(image); //Code for ToBitmapSource left out for brevity

        }

...
(3)  ShowViewModel.cs (just the SayHelloMethod)

        public void SayHello()  
        {
            WindowManager wm = new WindowManager();
            DisplayMessageViewModel dmvm = new DisplayMessageViewModel();
            dmvm.Textname = Textname;
            wm.Show(dmvm );
        }

 

Any help in wiring up the event please?
Thanks
rockmeister

Aug 5, 2010 at 9:02 AM
Edited Aug 5, 2010 at 9:03 AM

Though you could wire the event and haveImage1Initialized called (*), I suggest you to avoid this approach.
You should try to keep VM free from visualization concerns; you might try to build an IValueConverter which takes a string as input and "converts" it to an image.
This converter can be used to bind the Image.Source property to DisplayMessageViewModel.Textname property:

 

public class ToImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string displayString = string.Format("Hello Emgu {0}!", value);
		
		Image<Bgr, Byte> image = new Image<Bgr, byte>(400, 100, new Bgr(255, 255, 255));
		MCvFont f = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 3.0, 3.0);
		image.Draw(displayString, ref f, new System.Drawing.Point(10, 50), new Bgr(255.0, 0.0, 0.0));

		return ToBitmapSource(image); 
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
       throw new NotSupportedException();
    }
}

 

 

<Window  ...>
	<Window.Resources>
		<myNs:ToImageConverter x:Key="toImage"/>
	</Window.Resources>
	...
	<Image Stretch="Fill" Source="{Binding Textname, Converter={StaticResource toImage}}" />
	...
</Window>

 

Hope it helps.

 

 


(*) Just for completeness, you should be able to wire the Initialized event with 

<Image cal:Message.Attach="[Event Initialized] = [Action Image1Initialized]" />

 

 

Aug 6, 2010 at 12:57 AM

Hi marcoamendola
Thanks for the tip to keep VM free of visualization concerns.  It makes perfect sense.  I re-worked the sample based on your approach but I am still not getting the event fired.  I keep looking but have not figured out why.  Please help.
rockmeister

DisplayMessageView
==============

<Window x:Class="Caliburn.Micro.EmguHello.DisplayMessageView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Caliburn.Micro.EmguHello"
    Title="Window1" Height="303" Width="564">
    <Window.Resources>
        <local:ToImageConverter x:Key="toImage"/>
    </Window.Resources>
    <Grid>
        <Image x:Name="image1" Stretch="Fill" Source="{Binding Textname, Converter={StaticResource toImage}}" />
    </Grid>
</Window>

DisplayMessageViewModel
=======================
public
class DisplayMessageViewModel : PropertyChangedBase { string textname; public string Textname { get { return textname; } set { textname = value; NotifyOfPropertyChange(() => Textname); } } }
ToImageConverter
================
public class ToImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string displayString = string.Format("Hello Emgu {0}!", value);

            Image<Bgr, Byte> image = new Image<Bgr, byte>(400, 100, new Bgr(255, 255, 255));
            MCvFont f = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 3.0, 3.0);
            image.Draw(displayString, ref f, new System.Drawing.Point(10, 50), new Bgr(255.0, 0.0, 0.0));

            return ToBitmapSource(image);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
...

I captured the logs but could not see what could be going wrong.

Log
===
[2010-08-05T18:22:32.1067500-05:00] Binding System.Windows.Window+Caliburn.Micro.EmguHello.ShellViewModel.
[2010-08-05T18:22:32.1223750-05:00] Setting DC of System.Windows.Window to Caliburn.Micro.EmguHello.ShellViewModel.
[2010-08-05T18:22:32.1223750-05:00] Attaching message handler Caliburn.Micro.EmguHello.ShellViewModel to System.Windows.Window.
[2010-08-05T18:22:32.1380000-05:00] No bindable control for action get_Textname.
[2010-08-05T18:22:32.1380000-05:00] No bindable control for action set_Textname.
[2010-08-05T18:22:32.1380000-05:00] No bindable control for action get_CanSayHello.
[2010-08-05T18:22:32.1380000-05:00] Added convention action for SayHello as SayHello.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action add_PropertyChanged.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action remove_PropertyChanged.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action NotifyOfPropertyChange.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action NotifyOfPropertyChange.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action RaisePropertyChangedEventImmediately.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action ToString.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action Equals.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action GetHashCode.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for action GetType.
[2010-08-05T18:22:32.2317500-05:00] Added convention binding for Textname.
[2010-08-05T18:22:32.2317500-05:00] No bindable control for property CanSayHello.
[2010-08-05T18:22:32.2942500-05:00] Action: SayHello availability update.
[2010-08-05T18:22:37.5598750-05:00] Action: SayHello availability update.
[2010-08-05T18:22:37.6848750-05:00] Action: SayHello availability update.
[2010-08-05T18:22:40.3723750-05:00] Invoking Action: SayHello.
[2010-08-05T18:22:40.3723750-05:00] Binding Caliburn.Micro.EmguHello.DisplayMessageView+Caliburn.Micro.EmguHello.DisplayMessageViewModel.
[2010-08-05T18:22:40.3723750-05:00] Setting DC of Caliburn.Micro.EmguHello.DisplayMessageView to Caliburn.Micro.EmguHello.DisplayMessageViewModel.
[2010-08-05T18:22:40.3723750-05:00] Attaching message handler Caliburn.Micro.EmguHello.DisplayMessageViewModel to Caliburn.Micro.EmguHello.DisplayMessageView.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action get_Textname.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action set_Textname.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action add_PropertyChanged.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action remove_PropertyChanged.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action NotifyOfPropertyChange.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action NotifyOfPropertyChange.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action RaisePropertyChangedEventImmediately.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action ToString.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action Equals.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action GetHashCode.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for action GetType.
[2010-08-05T18:22:40.3723750-05:00] No bindable control for property Textname.
[2010-08-05T18:22:46.4661250-05:00] Action: SayHello availability update.
 

 

Coordinator
Aug 6, 2010 at 3:16 AM

What event was it you needed to fire? and what was supposed to execute as a result? I think I may be misunderstanding something in your description.

Aug 6, 2010 at 4:17 AM

Hi Rob

My terminology may be a little off...  Here is what I wanted to do...  when the user types in some text in the textbox and presses the "Click Me" button, I want to open a new Window and show an  Image of the text typed.

Steps
======
(1) In the ShellView when the user type say "World", I get the value on the Textname property in the ShellViewModel - Works
(2) When the user clicks on "Click Me" button, SayHelloMethod gets called - Works

public
void SayHello()
{
WindowManager wm = new WindowManager();
DisplayMessageViewModel dmvm = new DisplayMessageViewModel();
dmvm.Textname = Textname;
wm.Show(dmvm );
}
(3) I assign the Textname in the DisplayMessageViewModel and call the WindowManager.show(dmvm)
(4) My DsiplayMessageView is as follows
<Window x:Class="Caliburn.Micro.EmguHello.DisplayMessageView" ...
xmlns:local="clr-namespace:Caliburn.Micro.EmguHello"
Title="Window1" Height="303" Width="564">
<Window.Resources>
<local:ToImageConverter x:Key="toImage"/>
</Window.Resources>
<Grid>
<Image x:Name="image1" Stretch="Fill" Source="{Binding Textname, Converter={StaticResource toImage}}" />
</Grid>
</Window>

As part of View creation, I expected a call to the ToImageConverter.Convert method which will return the BitmapSource
public class ToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string displayString = string.Format("Hello Emgu {0}!", value);

Image<Bgr, Byte> image = new Image<Bgr, byte>(400, 100, new Bgr(255, 255, 255));
MCvFont f = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 3.0, 3.0);
image.Draw(displayString, ref f, new System.Drawing.Point(10, 50), new Bgr(255.0, 0.0, 0.0));

return ToBitmapSource(image);
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
However, the Convert method is never getting called. I just get the blank window with a blank Image showing up.
Hope that explains the problem I am having.
Thanks for your help.
rockmeister


Aug 6, 2010 at 9:39 AM

Following the converter path, event Initialized is unnecessary: the binding engine should bind the Image.Source property to the Textname property using the converter to "adapt" a string to an ImageSource.

There should be something wrong in my code (I wrote it in notepad, so I could have missed something). A few things I suggest you to check:

1) does binding a Textbox to Textname (just before the Image with no converter) work? There could be a problem in binding of the whole view if it doesn't work

2) does ToImageConverter get instantiated?

3) does ToImageConverter.Convert method get called? Not sure if an exception in that method could eventually be swallowed by the  binding engine.

 

Let me know if it helps you to diagnose the problem.

Aug 8, 2010 at 4:43 PM

Hi marcomendola
Thanks for your helpful suggestion. Finally, I had sometime today morning...  I put in some debug statement and found that even the binding to a Textbox wasn't working.  I had to change the DisplayMessageView from a Window to an UserControl and I called InitializedComponent() in the ctor.  I have a feeling that when the DisplayMessage was a window, since I cannot call InitializedComponent() the binding were not taking effect.  Not sure if this is my usage issue or a bug in CM.  Working code is below

DisplayMessageView.xaml

<UserControl x:Class="Caliburn.Micro.EmguHello.DisplayMessageView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Caliburn.Micro.EmguHello"
    Height="303" Width="564">
    <UserControl.Resources>
        <local:ToImageConverter x:Key="toImage"/>
    </UserControl.Resources>
    <Grid>
        <Image x:Name="image1" Stretch="Fill" Source="{Binding Textname, Converter={StaticResource toImage}}" />
    </Grid>
</UserControl>

DisplayMessageView.xaml.cs

public partial class DisplayMessageView : UserControl
    {
        static readonly ILog Log = LogManager.GetLog(typeof(DisplayMessageView));
        public DisplayMessageView()
        {
            Log.Info("into ctor of {0}", this);
            InitializeComponent();
        }
    }

Thanks a bunch for the help.
rockmeister