Link to home
Start Free TrialLog in
Avatar of BrentDenny
BrentDennyFlag for Afghanistan

asked on

Silverlight data binding to septate class c#

I have a canvas that i need to add some mouse events like mouse-leave and mouse-enter  ect...

i have a separate class that is  will be handling the mouse events but i need to bind them from that page to the separate class NOT to code behind. Here is were i have bound to the class USAmap
i have used it and it works just fine for properties  but I dont now how to bind the mouse events for a canvas.
 
 <UserControl.Resources>
        <ViewModel:USAmap x:Key="ViewModel" MapItemName="USmap"/>
     </UserControl.Resources>
    <Grid x:Name="LayoutRoot" DataContext="{Binding Source = {StaticResource ViewModel}}">


<Canvas x:Name="Washington" Width="600" Height="398" Canvas.Left="0" Canvas.Top="0">
                    <Path x:Name="Path" Width="72.6667" Height="52.6219" Canvas.Left="38.831" Canvas.Top="19.7767" Stretch="Fill" Fill="#671BA51B" Data="F1 M 38.831,51.7767L ect...."/>
                </Canvas>

Also is there a way to still find out what the sender is and access it.
to change its properties once clicked. like in the code example

public class USAmap ......

 public static MouseButtonEventHandler _routedEvent;

public void c_MouseMove(object sender, MouseEventArgs e)
        {
            Canvas c = sender as Canvas;
            ResetLastSelected();

            if (!string.IsNullOrEmpty(c.Name))
            {
                if (c.Name != lastSelected)
                {
                 //   HideMenu();
                }

                lastSelected = c.Name;
                lastSelected2 = c.Name + "_HotSpot";
               // Canvas selectedCanvas2 = this.FindName(lastSelected2) as Canvas;

              //  SetCanvasColor(c, Color.FromArgb(255, 127, 255, 0), 2, Colors.Green, selectedCanvas2);
            }
        }

Open in new window

Avatar of saragani
saragani

Hi, you will need to use system.windows.interactivity.dll and
Microsoft.expression.interactions

You will need to use the CallMethodAction behavior

If you have Blend 4 then it would be easier for you to define it.
Avatar of BrentDenny

ASKER

ok could you give me an example based on the code I gave you like on what pages I need to put what where and how it kinda all works together if you could please. Mean while ill see what i can find out about the interactivity and interactions  

I have blend but dont really know how to use it
P.S.I was trying to use the ICommand but since it only works that I can see for calling a fiction that doent work i need to access the sender to change it and it "e"  unless i am using it wrong.
Hi, I'm working on an example for you... And yes, you can also get the sender and the event args if you use the CallMethodAction
do you use the
 <UserControl.Resources>
        <ViewModel:USAmap x:Key="ViewModel" MapItemName="USmap"/>
     </UserControl.Resources>
still ?
You can do it differently..

Another way to set the DataContext is:

<UserControl.DataContext>
   <ViewModel:USAmap MapItemName="USmap"/>
</UserControl.DataContext>


Hi, this is the XAML:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ViewModel="clr-namespace:SilverlightCallMethodAction.ViewModel"
[b]    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" [/b]x:Class="SilverlightCallMethodAction.MainPage"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.DataContext>
        <ViewModel:USAmap MapItemName="USmap"//>
    </UserControl.DataContext>



    <Grid x:Name="LayoutRoot" Background="White">
        <Canvas x:Name="Washington" Width="600" Height="398" Canvas.Left="0" Canvas.Top="0" [b]Background="Transparent"[/b]>
[b]        	<i:Interaction.Triggers>
        		<i:EventTrigger EventName="MouseMove">
        			<ei:CallMethodAction TargetObject="{Binding}" MethodName="c_MouseMove"/>
        		</i:EventTrigger>
        	</i:Interaction.Triggers>[/b] 
           <Path x:Name="Path" Width="72.6667" Height="52.6219" Canvas.Left="38.831" Canvas.Top="19.7767" Stretch="Fill" Fill="#671BA51B"/>
        </Canvas>
    </Grid>
</UserControl>

Open in new window


Please note that I've added xmlns "i" and "ie".
You will need the DLLs I've mentioned earlier to be added to your references,

You will also see that the canvas background must have a value (else it is Null and therefore Hit Test does not happen).

And you will also see the section where I've defined the CallMethodAction.
The XAML got a little corrupted.. I added Bold , but the Code tags ignored it. Here it is without code tags:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ViewModel="clr-namespace:SilverlightCallMethodAction.ViewModel"
   xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="SilverlightCallMethodAction.MainPage"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.DataContext>
        <ViewModel:USAmap MapItemName="USmap"//>
    </UserControl.DataContext>



    <Grid x:Name="LayoutRoot" Background="White">
        <Canvas x:Name="Washington" Width="600" Height="398" Canvas.Left="0" Canvas.Top="0" Background="Transparent">
             <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseMove">
                          <ei:CallMethodAction TargetObject="{Binding}" MethodName="c_MouseMove"/>
                    </i:EventTrigger>
              </i:Interaction.Triggers>

           <Path x:Name="Path" Width="72.6667" Height="52.6219" Canvas.Left="38.831" Canvas.Top="19.7767" Stretch="Fill" Fill="#671BA51B"/>
        </Canvas>
    </Grid>
</UserControl>
Ok so first I am assuming that I have to do that for every mouse event like mouse leave  mouse over  ect i have 4 mouse events i need to do.  Also i have like 50 canvases (STATEs)with  the same with different points so is there a good way besides this to this to each State?

so would i have to do this?  and would i have to do this for each State or is there a better solution?

 Background="Transparent">
             <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseMove">
                          <ei:CallMethodAction TargetObject="{Binding}" MethodName="c_MouseMove"/>
                    </i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
                          <ei:CallMethodAction TargetObject="{Binding}" MethodName="c_MouseMove"/>
                    </i:EventTrigger>
<i:EventTrigger EventName="MouseLeftButtonUp">
                          <ei:CallMethodAction TargetObject="{Binding}" MethodName="c_MouseMove"/>
                    </i:EventTrigger>
<i:EventTrigger EventName="MouseLeftUp">
                          <ei:CallMethodAction TargetObject="{Binding}" MethodName="c_MouseMove"/>
                    </i:EventTrigger>

              </i:Interaction.Triggers>
You will need to have all 4 events defined in XAML since each of them calls a different function (or at least should)... and some of the events have different event args (on Mouse Move you have different args than mouse button down).


About the 50 canvases, then first, if you have in the same XAML 50 different canvasses then you are doing something wrong.

If each of the canvasses is located on a different XAML then maybe the method name is not the same...

If it does, then maybe define a UserControl that contains a Canvas with those events and just put this UserControl in anywhere you want (50 times if needed).
This way you only need to write events definitions once.
ok i am going to give you 3 of them out of the 50 so you under stand there the USA states that are paths that i am using the canvases to change colors and opacity depending on the mouse events.
They will all call the same mouse events  so all 4 mouse events need to be tied to each 50 states

<Canvas x:Name="Oregon" Width="600" Height="398" Canvas.Left="0" Canvas.Top="0">
                    <Path x:Name="Path_1" Width="86.8889" Height="74.2222" Canvas.Left="19.2755" Canvas.Top="51.7767" Stretch="Fill" Fill="#671BA51B"
 Data="F1 M 19.7199,107.777L 19.2755,104.666L 19.7199,107.777 Z "/>
                </Canvas>
<Canvas x:Name="Califonia" Width="600" Height="398" Canvas.Left="0" Canvas.Top="0">
                    <Path x:Name="Path_3" Width="87.1111" Height="149.111" Canvas.Left="11.2755" Canvas.Top="107.554" Stretch="Fill" Fill="#671BA51B" Data="F1 M 19.9421,107.554L 37.7199,112.888L 47.2755,115.332L 55.7199,117.332L 61.0533,118.666L 60.1644,122.666L 57.9421,130.888L 56.1644,136.888L 54.6088,144.888L 107.554 Z "/>
                </Canvas>
 <Canvas x:Name="Arizona" Width="600" Height="398" Canvas.Left="0" Canvas.Top="0">
                    <Path x:Name="Path_5" Width="74" Height="85.8333" Canvas.Left="87.1366" Canvas.Top="200.443" Stretch="Fill" Fill="#671BA51B" Data="F1 M 87.9699,256.11L 88.9699,256.943L 90.6366,256.61L 91.9699,255.277L 91.9699,253.777L 90.4699,252.777L 89.6366,251.443L 89.6366,248.61L 90.4699,246.777L 92.1366,1366,257.777L 87.9699,256.11 Z "/>
                </Canvas>
P.S. the test is working just need think is there something in the app.xaml  that would be a good idea not sure i have just stared learn silver light 2 weeks ago.
Can't you gave just one canvas, and have all the paths in it??
Can't you on the mouse move of the canvas find which path your mouse is on?
not total because some states have multiple paths and the there would be a lot of code re-write since everything works i just pulling out every thing from the code be hind to a class that I can use the mvvm model more effectively since there are multiple maps that will use this class, so that would be counter productive there will be 50 other maps with similar attributes especially the mouse events
oops So i was hopping for like a for global event thing that the each canvas can use
well, if you really want to have it on the canvas without replicating the code then maybe you can create your own class that derives from Canvas.

In your class (Lets call it MyCanvas) code-behind register to the events you want...
And then do:
dynamic dataContext = this.DataContext;
dataContext.c_MouseMove(sender, e);

I'm using dynamic here, cause the canvas doesn't know the type of the viewmodel... I know, this is ugly.


A more proper design would be having an ItemsControl which has the ItemsPanel as Canvas and then the DataTemplate of the Items would be paths... just a suggestion.
I know DataTemplate is not supported by Silverlight, but you can still do it with a Converter. (a Converter that converts a ViewModel to it's proper UI).
I was going to try the approce of using the MyCanvas  but i am not sure what you mean by register to the the event and not sure where and what to do with the dynamic dataContext = this.DataContext;
dataContext.c_MouseMove(sender, e); sorry i was trying to look for examples but have found none
  public class CustCanvas : Panel
    {
        public CustCanvas()
        {
            dynamic dataContext = this.DataContext;
        //dataContext.c_MouseMove(sender, e);
        }
       
       // put the mouse event here or some how conect back to USAmap using a deligate?
        public void c_MouseMove(object sender, MouseEventArgs e)
        {
         
        }

    }
ASKER CERTIFIED SOLUTION
Avatar of saragani
saragani

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I thank you for you solution i could not get the exact something to work kept giving me a circle reference not sure why but then i just took out from the class i had and just used this as a template and it works great  for your help i am going to close this i need help with another problem and would like you get get more credit for it so i am going to call it navigation Sivlerlight

THanks again