Binding Confusion with ContextMenus

Oystein Bjorke 10 years ago 0
This discussion was imported from CodePlex

jstrang3 wrote at 2013-09-04 23:01:

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.

everytimer wrote at 2013-09-04 23:22:

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.

jstrang3 wrote at 2013-09-05 14:54:

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.

everytimer wrote at 2013-09-05 15:55:

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.

jstrang3 wrote at 2013-09-05 16:26:

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.

everytimer wrote at 2013-09-05 17:37:

Then bind the command to a button, that will work.

objo wrote at 2013-09-06 07:08:

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.

DrStrangeLove wrote at 2013-09-06 22:12:

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.