views:

124

answers:

2

I have a ContextMenu with a MenuItem in it:

<Grid>
    <Button Content="{Binding Test}">
        <Button.ContextMenu>
            <ContextMenu>
                <StackPanel>
                    <MenuItem Header="{Binding Test}"/>
                </StackPanel>
            </ContextMenu>
        </Button.ContextMenu>
    </Button>
</Grid>

The Test property looks like the following:

private Random rand;

public string Test
{
    get
    {
        return "Test " + this.rand.Next(50);
    }
}

When I right click the button, I have, for instance "Test 41". Next times I open the menu I have the same value. Is there a way to force the Menu to evaluate the binding each time ? (and then having "Test 3", "Test 45", "Test 65"...

A: 

Your Test property needs to inform other components whenever its value changes, e.g. by implementing the INotifyPropertyChanged interface in the containing class like this:

class Window1 : Window, INotifyPropertyChanged {

  ...

  private string m_Test;

  public string Test {
    get {
      return m_Test;
    }
    set {
      m_Test = value;
      OnPropertyChanged("Test");
    }
  }

}

You can then modify the value of Test from anywhere by using the property (Test = "newValue";) and the changes will be reflected on the UI.

If you really need to change the value of the property when the ContextMenu is shown, use the Opend event of the ContextMenu:

Xaml:

<ContextMenu Opened="UpdateTest">
  <MenuItem Header="{Binding Test}" />
</ContextMenu>

Code-behind:

private void UpdateTest(object sender, RoutedEventArgs e) {
  // just assign a new value to the property,
  // UI will be notified automatically
  Test = "Test " + this.rand.Next(50);
}
Julien Poulin
I think you don't get it, sorry if I'm unclear. I'm aware of the INotifyPropertyChanged stuff. I don't want to assign a new value to the Test property. I'd just like that every time the menu is opened its value is re-evaluated.
Jalfp
+1  A: 

Here is a hack i use in the same situation:

Name your context menu and create your own RoutedCommand, i use these for all buttons and menus as they have a CanExecute method which enables or disables the control and an Execute method that gets called to do the work. every time a context menu opens the CanExecute method gets called. that means you can do custom processing to see if it should be enabled, or you can change the contents of the menu, good for changing menu's when saving different things. we use it to say, Save xyx.. when the user is editing an xyx.

anyway if the menu is named you can modify its content on the CanExecute. (if the command originates on the menu you will have it as the sender of the event CanExecute anyway, but sometimes i like to scope them higher as you can assign keyboard shortcuts to them which can be executed from anywhere they are scoped.)

Aran Mulholland