Binding Confusion with ContextMenus

Sep 4, 2013 at 9:01 PM
Edited Sep 5, 2013 at 1:22 PM
Trying to bind a data source in MVVM and confused on why the data does not seem to be binding.
<oxy:Plot Grid.Row="0" x:Name="BalancesByPeriodChart"
                  LegendPlacement="Outside"
                  LegendPosition="BottomCenter"
                  LegendOrientation="Horizontal"
                  LegendSymbolLength="30"
                  LegendBorder="#000000"
                  LegendBorderThickness="1"
                  LegendFontSize="14"
                  PlotMargins="54,10,10,50"
                  HorizontalContentAlignment="Stretch"
                  VerticalContentAlignment="Stretch"            
                  KeyboardPanHorizontalStep="-0.1"
                  KeyboardPanVerticalStep="-0.1"
                  Model="{Binding ChartViewModel}"
                  Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type oxy:Plot}}, Path=Model}"
                  >

            <oxy:Plot.ContextMenu>
                <ContextMenu ItemsSource="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self} }">
                    <MenuItem Command="{Binding Plot.HideGraph1}" Header="Foo" 
                              IsCheckable="True" IsChecked="True"/>
                    <MenuItem Command="{Binding Plot.HideGraph2}" Header="Foo2" 
                              IsCheckable="True" IsChecked="True"/>
                </ContextMenu>
            </oxy:Plot.ContextMenu>
With this code I am trying to make a context menu so I can eventually set the visibility of two different graphs to hidden. The context menu shows up but when I click on either option, the command in the modelview is not triggered. Any help with this problem is greatly appreciated.
Sep 4, 2013 at 9:22 PM
Edited Sep 5, 2013 at 2:00 PM
Are you sure that you are binding correctly?
Plot.HideGraph2
This seems weird for me, where the command is located? Is the datacontext set correctly? First try simple operation when you're starting to wiring the commands, try if your commands are working with a MessegeBox. If your bindings are okey: a common mistake is to forget to update the plot. Show the actual code in your command so we can help you.
Sep 5, 2013 at 12:54 PM
I am trying to make a simple messagebox appear for my command. I am pretty sure that my bindings are incorrect, and that is what I need help with. The binding of a context menu is confusing to me. So helping with the binding would be great.
Sep 5, 2013 at 1:55 PM
Edited Sep 5, 2013 at 1:59 PM
I don't know why the binding isn't working. If you really need to perform a command in your bound ViewModel you can do the following:

Create a new static class Mediator:
 static public class Mediator
    {
        static IDictionary<string, List<Action<object>>> pl_dict = new Dictionary<string, List<Action<object>>>();

        static public void Register(string token, Action<object> callback)
        {
            if (!pl_dict.ContainsKey(token))
            {
                var list = new List<Action<object>>();
                list.Add(callback);
                pl_dict.Add(token, list);
            }
            else
            {
                bool found = false;
                foreach (var item in pl_dict[token])
                    if (item.Method.ToString() == callback.Method.ToString())
                        found = true;
                if (!found)
                    pl_dict[token].Add(callback);
            }
        }

        static public void Unregister(string token, Action<object> callback)
        {
            if (pl_dict.ContainsKey(token))
                pl_dict[token].Remove(callback);
        }

        static public void NotifyColleagues(string token, object args)
        {
            if (pl_dict.ContainsKey(token))
                foreach (var callback in pl_dict[token])
                    callback(args);
        }
}
In your MenuItem set the click event:
                    <MenuItem Header="Mediator!" Click="MenuItem_Click_1" />
Code behind notify the message:

        private void MenuItem_Click_1(object sender, RoutedEventArgs e)
        {
            Mediator.NotifyColleagues("menu1", null);
        }
Don't forget to register to listen the message in your ViewModel constructor:
            Mediator.Register("menu1", yourMethod);
        void yourMethod(object param)
        {
            MessageBox.Show("Hey!");
            myLineSeries.IsVisible = !myLineSeries.IsVisible;
        }
Done!

If would be nice if someone could tell us if he can achieve the binding to command in the context menu.
Sep 5, 2013 at 2:26 PM
Can not use the code behind, so I have to do all the binding in the xaml. This makes the task a little more difficult. Also, I have been trying different bindings and nothing seems to be working for me. So I am open to suggestions, that do not use code behind.
Sep 5, 2013 at 3:37 PM
Edited Sep 5, 2013 at 3:37 PM
Then bind the command to a button, that will work.
Coordinator
Sep 6, 2013 at 5:08 AM
I tried to use a {Binding PresentationTraceSources.TraceLevel=High} and it seems the data context is not passed to the context menu. I don't know why..
I added this.ContextMenu.DataContext = this.DataContext; to the Plot control, just before it shows the context menu.
I am not sure if this is an ok way to solve it, but it seems to work.
Sep 6, 2013 at 8:12 PM
My problem is that I am using the MVVM model, and I do not have any code behind, so the view is only xaml. Which does not allow me to connect directly to the plot or anything in it. So is there a way to do the same thing in the xaml that you suggested in the code behind.