与对象关联的WPF动态菜单?

时间:2010-10-19 00:02:49

标签: wpf binding

我希望能够创建与某个对象关联的动态菜单。比方说,我将有3个listview容器,其中一个样式我也有一个菜单。我需要从每个列表视图中的RoutetUICommands集合中生成不同的菜单项。我试图解决这个难题,但我花了一段时间仍然无法使它工作。我需要生成特定于对象的菜单,每个列表视图都有一个独特的菜单。任何想法都受到高度赞赏。谢谢!

XAML:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
x:Class="DynamicMenu.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>

    <Style x:Key="ListViewStyleTask" TargetType="{x:Type ListView}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListView}">
                    <Grid>
                        <Menu x:Name="mainMenu">
                            <MenuItem x:Name="menuItem" Header="Tasks" ItemsSource="{Binding Commands}" >
                                <MenuItem.ItemContainerStyle>
                                    <Style TargetType="{x:Type MenuItem}">
                                        <Setter Property="Command" Value="{Binding}" />
                                        <Setter Property="Header" Value="{Binding Path=Text}" />
                                        <Setter Property="CommandParameter" Value="{Binding Path=Parameter}" />
                                    </Style>
                                </MenuItem.ItemContainerStyle>
                            </MenuItem>
                        </Menu>
                    </Grid>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>

<Grid x:Name="LayoutRoot">
    <ListView x:Name="Container1" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" Style="{DynamicResource ListViewStyleTask}">
        <ListView.View>
            <GridView>
                <GridViewColumn/>
            </GridView>
        </ListView.View>
    </ListView>
    <ListView x:Name="Container2" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" Style="{DynamicResource ListViewStyleTask}">
        <ListView.View>
            <GridView>
                <GridViewColumn/>
            </GridView>
        </ListView.View>
    </ListView>
    <ListView x:Name="Container3" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" Style="{DynamicResource ListViewStyleTask}">
        <ListView.View>
            <GridView>
                <GridViewColumn/>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

I have added some commands which I need to associate to 3 different Listviews:

    public partial class MainWindow : Window
{

    // Container 1
    public static RoutedUICommand NameCommand = new RoutedUICommand("Name", "NameCommand", typeof(MainWindow));
    public static RoutedUICommand StreetCommand = new RoutedUICommand("Street", "StreetCommand", typeof(MainWindow));
    public static RoutedUICommand GroupCommand = new RoutedUICommand("Add to Group", "AddGroup", typeof(MainWindow));

    // Container 2
    public static RoutedUICommand ViewDetailsCommand = new RoutedUICommand("View Details", "ViewDetailsCommand", typeof(MainWindow));

    // Container 3
    public static RoutedUICommand StartCommand = new RoutedUICommand("Start", "StartCommand", typeof(MainWindow));
    public static RoutedUICommand StopCommand = new RoutedUICommand("Stop", "StopCommand", typeof(MainWindow));
    public static RoutedUICommand LoadCommand = new RoutedUICommand("Load", "LoadCommand", typeof(MainWindow));

    public MainWindow()
    {
        this.InitializeComponent();

        // Insert code required on object creation below this point.
    }
}

}

1 个答案:

答案 0 :(得分:2)

您需要定义一个结构,以便在控件模板中根据需要对数据进行分组。像这样的东西,

public class CommandCollection {
    public ObservableCollection<Command> Commands { get; set; }
}

public class Command {

    public ICommand Action { get; set; }

    public string Text { get; set; }

    public string Parameter { get; set; }
}

CommandCollection的3个成员各自拥有其命令,然后将这些成员作为datacontext分配给ListViews

更新

在声明上述结构后,您声明了3个成员

public CommandCollection Container1Commands { get; set; }

public CommandCollection Container2Commands { get; set; }

public CommandCollection Container3Commands { get; set; }

填写这些成员,

    Container1Commands = new CommandCollection ();
    Container1Commands.Commands = new ObservableCollection<CommandParameters> ();
    Container1Commands.Commands.Add (new CommandParameters () { Action = NameCommand, Text = "Name" });
    Container1Commands.Commands.Add (new CommandParameters () { Action = StreetCommand, Text = "Street" });
    Container1Commands.Commands.Add (new CommandParameters () { Action = GroupCommand, Text = "Group" });

    Container2Commands = new CommandCollection ();
    Container2Commands.Commands = new ObservableCollection<CommandParameters> ();
    Container2Commands.Commands.Add (new CommandParameters () { Action = ViewDetailsCommand, Text = "ViewDetails" });

    Container3Commands = new CommandCollection ();
    Container3Commands.Commands = new ObservableCollection<CommandParameters> ();
    Container3Commands.Commands.Add (new CommandParameters () { Action = StartCommand, Text = "Start" });
    Container3Commands.Commands.Add (new CommandParameters () { Action = StopCommand, Text = "Stop" });
    Container3Commands.Commands.Add (new CommandParameters () { Action = LoadCommand, Text = "Load" });

设置数据上下文,

    this.DataContext = this;
    this.Container1.DataContext = Container1Commands;
    this.Container2.DataContext = Container2Commands;
    this.Container3.DataContext = Container3Commands;

更新控件模板以指定菜单项命令绑定

<Setter Property="Command" Value="{Binding Action}" />

<强>更新 XAML

    <Window.Resources>

        <Style x:Key="ListViewStyleTask" TargetType="{x:Type ListView}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListView}">
                        <Grid>
                            <Menu x:Name="mainMenu" >
                                <MenuItem x:Name="menuItem" Header="Tasks" ItemsSource="{Binding Commands}">
                                    <MenuItem.ItemContainerStyle>
                                        <Style TargetType="{x:Type MenuItem}">
                                            <Setter Property="Command" Value="{Binding Action}" />
                                            <Setter Property="Header" Value="{Binding Path=Text}" />
                                            <Setter Property="CommandParameter" Value="{Binding Path=Parameter}" />
                                        </Style>
                                    </MenuItem.ItemContainerStyle>
                                </MenuItem>
                            </Menu>
                        </Grid>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Window.Resources>

    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ListView
            Grid.Row="0" x:Name="Container1" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" Style="{DynamicResource ListViewStyleTask}">
            <ListView.View>
                <GridView>
                    <GridViewColumn/>
                </GridView>
            </ListView.View>
        </ListView>
        <ListView
            Grid.Row="1" x:Name="Container2" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" Style="{DynamicResource ListViewStyleTask}">
            <ListView.View>
                <GridView>
                    <GridViewColumn/>
                </GridView>
            </ListView.View>
        </ListView>
        <ListView
            Grid.Row="2" x:Name="Container3" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" Style="{DynamicResource ListViewStyleTask}">
            <ListView.View>
                <GridView>
                    <GridViewColumn/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>

背后的代码

// Container 1
public static RoutedUICommand NameCommand = new RoutedUICommand ("Name", "NameCommand", typeof (Window1));
public static RoutedUICommand StreetCommand = new RoutedUICommand ("Street", "StreetCommand", typeof (Window1));
public static RoutedUICommand GroupCommand = new RoutedUICommand ("Add to Group", "AddGroup", typeof (Window1));

// Container 2
public static RoutedUICommand ViewDetailsCommand = new RoutedUICommand ("View Details", "ViewDetailsCommand", typeof (Window1));

// Container 3
public static RoutedUICommand StartCommand = new RoutedUICommand ("Start", "StartCommand", typeof (Window1));
public static RoutedUICommand StopCommand = new RoutedUICommand ("Stop", "StopCommand", typeof (Window1));
public static RoutedUICommand LoadCommand = new RoutedUICommand ("Load", "LoadCommand", typeof (Window1));

public Window1 () {
    InitializeComponent ();
    this.Loaded += new RoutedEventHandler (Window1_Loaded);
}

public CommandCollection Container1Commands { get; set; }

public CommandCollection Container2Commands { get; set; }

public CommandCollection Container3Commands { get; set; }

void Window1_Loaded (object sender, RoutedEventArgs e) {
    Container1Commands = new CommandCollection ();
    Container1Commands.Commands = new ObservableCollection<Command> ();
    Container1Commands.Commands.Add (new Command () { Action = NameCommand, Text = "Name" });
    Container1Commands.Commands.Add (new Command () { Action = StreetCommand, Text = "Street" });
    Container1Commands.Commands.Add (new Command () { Action = GroupCommand, Text = "Group" });

    Container2Commands = new CommandCollection ();
    Container2Commands.Commands = new ObservableCollection<Command> ();
    Container2Commands.Commands.Add (new Command () { Action = ViewDetailsCommand, Text = "ViewDetails" });

    Container3Commands = new CommandCollection ();
    Container3Commands.Commands = new ObservableCollection<Command> ();
    Container3Commands.Commands.Add (new Command () { Action = StartCommand, Text = "Start" });
    Container3Commands.Commands.Add (new Command () { Action = StopCommand, Text = "Stop" });
    Container3Commands.Commands.Add (new Command () { Action = LoadCommand, Text = "Load" });

    this.CommandBindings.Add (new CommandBinding (NameCommand, ExecuteNameCommand, CanExecuteNameCommand));
    this.CommandBindings.Add (new CommandBinding (StreetCommand, ExecuteStreetCommand, CanExecuteStreetCommand));
    this.CommandBindings.Add (new CommandBinding (GroupCommand, ExecuteGroupCommand, CanExecuteGroupCommand));

    this.DataContext = this;
    this.Container1.DataContext = Container1Commands;
    this.Container2.DataContext = Container2Commands;
    this.Container3.DataContext = Container3Commands;
}

private void ExecuteNameCommand (object inSender, RoutedEventArgs inE) {
    MessageBox.Show ("Name command Executed");
}

private void CanExecuteNameCommand (object inSender, CanExecuteRoutedEventArgs inE) {
    inE.CanExecute = true;
}

private void ExecuteStreetCommand (object inSender, RoutedEventArgs inE) {
    MessageBox.Show ("Street command Executed");
}

private void CanExecuteStreetCommand (object inSender, CanExecuteRoutedEventArgs inE) {
    inE.CanExecute = true;
}

private void ExecuteGroupCommand (object inSender, RoutedEventArgs inE) {
    MessageBox.Show ("Group command Executed");
}

private void CanExecuteGroupCommand (object inSender, CanExecuteRoutedEventArgs inE) {
    inE.CanExecute = true;
}

其他课程

public class CommandCollection {

    public ObservableCollection<Command> Commands { get; set; }
}

public class Command {

    public ICommand Action { get; set; }

    public string Text { get; set; }

    public string Parameter { get; set; }
}

我希望你能让它运转起来。

针对RoutedUICommand描述进行了更新, 想法应该是在外部容器(如shell)中有这些菜单项,其中将包含其他页面(如框架/画布),例如,如果您看到MS Visual Studio,则菜单项(保存)是其中的一部分应用程序shell和打开的文件都在shell中(shell可能有一个容器tabcontrol,文件在打开时加载)。因此,路由命令(保存)由应用程序shell定义,并且shell容器内的所有其他页面在命令绑定集合(this.CommandBindings.Add(cmdname, actionname, predicatename))中添加这些命令,因此每个页面执行各自的操作并调用命令只有当他们聚焦时才能使用它们。