Domanda

I've got some XAML like the following:

<UserControl x:Class="Foo">
  <UserControl.Resources>
    <ContextMenu x:Key="ContextMenu1">
      <MenuItem Header="Command 1a"/>
      <MenuItem Header="Command 1b"/>
    </ContextMenu>
    <ContextMenu x:Key="ContextMenu2">
      <MenuItem Header="Command 2a"/>
      <MenuItem Header="Command 2b"/>
    </ContextMenu>
  </UserControl.Resources>

  <DockPanel>
    <TreeView>
      <TreeView.Resources>
        <DataTemplate DataType="{x:Type Type1}">
          <StackPanel ContextMenu="{StaticResource ContextMenu1"}/>
        </DataTemplate>

        <DataTemplate DataType="{x:Type Type2}">
          <StackPanel ContextMenu="{StaticResource ContextMenu2"}/>
        </DataTemplate>
      </TreeView.Resources>
    </TreeView>
  </DockPanel>
</UserControl>

and a code behind similar to the following:

public class Type1 {
  public void OnCommand1a() {}
  public void OnCommand1b() {}
}

public class Type2 {
  public void OnCommand2a() {}
  public void OnCommand2b() {}
}

What do I need to do so that clicking the respective items on the menus calls the corresponding function?

If I add:

Command="{Binding Path=OnCommand1a}" CommandTarget="{Binding Path=PlacementTarget}"

etc then at runtime I get errors about how OnCommand1a is not a property. Some searching suggests this has something to do with a RoutedUIEvent, but I don't really understand what that's about.

If I use

Click="OnCommand1a" 

then it looks for OnCommand1a() on the UserControl instead of on the type that is bound to the DataTemplate.

What is the standard way of dealing this?

È stato utile?

Soluzione

First of all you need a class that extends ICommand. You can use this:

public class DelegateCommand : ICommand
{
    private readonly Action<object> executeMethod = null;
    private readonly Func<object, bool> canExecuteMethod = null;

    public event EventHandler CanExecuteChanged
    {
        add { return; }
        remove { return; } 
    }

    public DelegateCommand(Action<object> executeMethod, Func<object, bool> canExecuteMethod)
    {
        this.executeMethod = executeMethod;
        this.canExecuteMethod = canExecuteMethod;
    }

    public bool CanExecute(object parameter)
    {
        if (canExecuteMethod == null) return true;
        return this.canExecuteMethod(parameter);
    }

    public void Execute(object parameter)
    {
        if (executeMethod == null) return;
        this.executeMethod(parameter);
    }
}

Then, in your class Type1 you have to declare this:

public DelegateCommand OnCommand1a {get; private set;}

and set it in your Type1 constructor in this way:

OnCommand1a = new DelegateCommand(c => Cmd1a(), null);

where Cmd1a is:

private void Cmd1a()
{
     //your code here
}

Finally, in your xaml:

Command="{Binding Path=OnCommand1a}"    
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top