WPF绑定到ListBox的ContextMenu的MenuItem中的IsEnabled属性 [英] WPF Binding to IsEnabled Property in ListBox' ContextMenu's MenuItem

查看:152
本文介绍了WPF绑定到ListBox的ContextMenu的MenuItem中的IsEnabled属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看与上下文菜单数据绑定有关的其他主题,但由于建议/答案对我不起作用,因此我无法弄清楚如何使其起作用.

我有一个列表框,该列表框绑定到一个ObversableCollection-运行正常.

现在我在该列表框中有一个上下文菜单.该contextmenu有4个项目可以激活,停用等选定的任务(这是列表框中显示的项目).

由于权限的原因,我需要控制上下文菜单中的项是启用还是禁用,因此我必须通过将ContextMenuItem的IsEnabled-Property绑定到与列表框绑定到的同一Collection来设置./p>

但是由于某些原因,上下文菜单项没有被禁用-该属性似乎被忽略了.


编辑:我现在已经实施了您的建议:

WPF

<ListView Margin="10,10,10,55" Name="listviewCurrentJobs" ItemsSource="{Binding JobCollection}">
    <ListView.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Starten" Command="{Binding Path=startCommand}"/>
            <MenuItem Header="Stoppen" Command="{Binding Path=stopCommand}"/>
            <MenuItem Header="Aktivieren" Command="{Binding Path=enableCommand}"/>
            <MenuItem Header="Deaktivieren" Command="{Binding Path=disableCommand}"/>
            <MenuItem Header="Löschen" Command="{Binding Path=deleteCommand}"/>
        </ContextMenu>
    </ListView.ContextMenu>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="" Width="32">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image Source="{Binding State}" Width="16"/>
                        </StackPanel>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Description}" />
        </GridView>
    </ListView.View>
</ListView>

C#

public class currentJob : MonitoringWindow
{
    public string State { get; set; }
    public string Description { get; set; }

    public bool startPermitted { get; set; }
    public bool stopPermitted { get; set; }
    public bool enablePermitted { get; set; }
    public bool disablePermitted { get; set; }
    public bool deletePermitted { get; set; }

    public ICommand StartCommand { get; private set; }
    public ICommand StopCommand { get; private set; }
    public ICommand EnableCommand { get; private set; }
    public ICommand DisableCommand { get; private set; }
    public ICommand DeleteCommand { get; private set; }

    public currentJob()
    {
        StartCommand = new DelegateCommand(ExecuteStart, CanExecuteStart);
        StopCommand = new DelegateCommand(ExecuteStop, CanExecuteStop);
        EnableCommand = new DelegateCommand(ExecuteEnable, CanExecuteEnable);
        DisableCommand = new DelegateCommand(ExecuteDisable, CanExecuteDisable);
        DeleteCommand = new DelegateCommand(ExecuteDelete, CanExecuteDelete);
    }

    public bool CanExecuteStart()
    {
        return startPermitted;
    }
    public bool CanExecuteStop()
    {
        return stopPermitted;
    }
    public bool CanExecuteEnable()
    {
        return enablePermitted;
    }
    public bool CanExecuteDisable()
    {
        return disablePermitted;
    }
    public bool CanExecuteDelete()
    {
        return deletePermitted;
    }

    public void ExecuteStart()
    {
        currentJob curJob = ((currentJob)listviewCurrentJobs.SelectedItem);
        string curJobName = curJob.Name;
        if (new TaskService().GetFolder("DocuWare Notifications").Tasks[curJobName].Enabled == false)
            new TaskService().GetFolder("DocuWare Notifications").Tasks[curJobName].Enabled = true;
        new TaskService().GetFolder("DocuWare Notifications").Tasks[curJobName].Run();
        loadJobs();
    }
    public void ExecuteStop()
    {
        if (new TaskService().GetFolder("DocuWare Notifications").Tasks[((currentJob)listviewCurrentJobs.SelectedItem).Name].Enabled == true)
        {
            new TaskService().GetFolder("DocuWare Notifications").Tasks[((currentJob)listviewCurrentJobs.SelectedItem).Name].Stop();
            loadJobs();
        }
    }
    public void ExecuteEnable()
    {
        new TaskService().GetFolder("DocuWare Notifications").Tasks[((currentJob)listviewCurrentJobs.SelectedItem).Name].Enabled = true;
        loadJobs();
    }
    public void ExecuteDisable()
    {
        new TaskService().GetFolder("DocuWare Notifications").Tasks[((currentJob)listviewCurrentJobs.SelectedItem).Name].Enabled = false;
        loadJobs();
    }
    public void ExecuteDelete()
    {
        new TaskService().GetFolder("DocuWare Notifications").DeleteTask(((currentJob)listviewCurrentJobs.SelectedItem).Name);
        if (isMsSql)
        {
            mssqlconn.Open();
            new SqlCommand("DELETE FROM dbo.DocuWareNotifications WHERE NAME = '" + ((currentJob)listviewCurrentJobs.SelectedItem).Name + "'", mssqlconn).ExecuteNonQuery();
            mssqlconn.Close();
        }
        else
        {
            mysqlconn.Open();
            new MySqlCommand("DELETE FROM DocuWareNotifications WHERE NAME = '" + ((currentJob)listviewCurrentJobs.SelectedItem).Name + "'", mysqlconn).ExecuteNonQuery();
            mysqlconn.Close();
        }
        loadJobs();
    }
}

public partial class MonitoringWindow : MetroWindow
{
    [...]
    foreach (Task task in new TaskService().GetFolder("DocuWare Notifications").Tasks)
    {
        if (task != null)
        {
            currentJob item = new currentJob();
            switch (task.State)
            {
                case TaskState.Disabled:
                    item.State = "/DWNotDesigner;component/images/disabled.png";
                    item.Description = task.Name;
                    break;
                case TaskState.Ready:
                    item.State = "/DWNotDesigner;component/images/active.png";
                    item.Description = task.Name;
                    break;
                case TaskState.Running:
                    item.State = "/DWNotDesigner;component/images/working.png";
                    item.Description = task.Name;
                    break;
            }
            item.startPermitted = startPermitted;
            item.stopPermitted = stopPermitted;
            item.enablePermitted = enablePermitted;
            item.disablePermitted = disablePermitted;
            item.deletePermitted = deletePermitted;
            _jobCollection.Add(item);
        }
    }
}

由于某些原因,没有变化!

解决方案

您可以尝试使用命令绑定(您需要

...

using Microsoft.Practices.Composite.Presentation.Commands;

public class currentJob
{
    public ICommand StartCommand {get; private set;}
    public currentJob ()
    {
         StartCommand = new DelegateCommand(ExecuteStart, CanExecuteStart); 
    }

    private bool CanExecuteStart()
    {
        //Determine whether start can be executed
        return true;
    }

    private void ExecuteStart()
    {
        //start here
    }
}

在这里,在原始示例中,ExecuteStart替换了startJob,而CanExecuteStart替换了enablePermitted.


编辑这可能有助于解释为什么原始代码无法正常工作.仅当属性对象触发"PropertyChange"事件时,才会拾取对绑定属性的更改.实施 INotifyPropertyChanged 也可能会解决您的问题.


编辑与原始代码相比,一个更琐碎的问题是它绑定到了错误的对象-我认为FeedContextMenu上不存在startPermitted属性(无论如何似乎都没有定义).


编辑上面还有一些问题: 1)绑定区分大小写,因此绑定应为{Binding StartCommand}等. 2)您需要在列表中的各个项目上设置上下文菜单.以下将起作用:

    <ListView Margin="10,10,10,55" Name="listviewCurrentJobs" ItemsSource="{Binding JobCollection}">
        <ListView.ItemTemplate>
                <DataTemplate>
                <Border BorderBrush="Black" BorderThickness="2">
                    <StackPanel Orientation="Horizontal" MinHeight="20" Background="White">
                        <StackPanel.ContextMenu>
                            <ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
                                <MenuItem Header="Starten" Command="{Binding Path=StartCommand}"/>
                                <MenuItem Header="Stoppen" Command="{Binding Path=StopCommand}"/>
                                <MenuItem Header="Aktivieren" Command="{Binding Path=EnableCommand}"/>
                                <MenuItem Header="Deaktivieren" Command="{Binding Path=DisableCommand}"/>
                                <MenuItem Header="Löschen" Command="{Binding Path=DeleteCommand}"/>
                            </ContextMenu>
                        </StackPanel.ContextMenu>
                        <Image Source="{Binding State}" Width="16"/>
                    </StackPanel>
                </Border>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

i was looking at the other threads regarding databinding to contextmenus but i couldnt figure out how to get it to work since the suggestions/answers wouldnt work for me.

i have a listbox, which is bound to an ObversableCollection - that works fine.

now i have a contextmenu inside that listbox. that contextmenu has 4 items to activate, deactivate etc the selected task (which is the item that is represented in the listbox).

due to permissions, i need to control, wether the items in the contextmenu are enabled or disabled, so i have to set the IsEnabled-Property of the ContextMenuItem by binding it to the same Collection that the Listbox is bound to.

but for some reason, the contextmenu items are not getting disabled - the property seems to be ignored.


EDIT: i have now implemented your suggestion:

WPF

<ListView Margin="10,10,10,55" Name="listviewCurrentJobs" ItemsSource="{Binding JobCollection}">
    <ListView.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Starten" Command="{Binding Path=startCommand}"/>
            <MenuItem Header="Stoppen" Command="{Binding Path=stopCommand}"/>
            <MenuItem Header="Aktivieren" Command="{Binding Path=enableCommand}"/>
            <MenuItem Header="Deaktivieren" Command="{Binding Path=disableCommand}"/>
            <MenuItem Header="Löschen" Command="{Binding Path=deleteCommand}"/>
        </ContextMenu>
    </ListView.ContextMenu>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="" Width="32">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image Source="{Binding State}" Width="16"/>
                        </StackPanel>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Description}" />
        </GridView>
    </ListView.View>
</ListView>

C#

public class currentJob : MonitoringWindow
{
    public string State { get; set; }
    public string Description { get; set; }

    public bool startPermitted { get; set; }
    public bool stopPermitted { get; set; }
    public bool enablePermitted { get; set; }
    public bool disablePermitted { get; set; }
    public bool deletePermitted { get; set; }

    public ICommand StartCommand { get; private set; }
    public ICommand StopCommand { get; private set; }
    public ICommand EnableCommand { get; private set; }
    public ICommand DisableCommand { get; private set; }
    public ICommand DeleteCommand { get; private set; }

    public currentJob()
    {
        StartCommand = new DelegateCommand(ExecuteStart, CanExecuteStart);
        StopCommand = new DelegateCommand(ExecuteStop, CanExecuteStop);
        EnableCommand = new DelegateCommand(ExecuteEnable, CanExecuteEnable);
        DisableCommand = new DelegateCommand(ExecuteDisable, CanExecuteDisable);
        DeleteCommand = new DelegateCommand(ExecuteDelete, CanExecuteDelete);
    }

    public bool CanExecuteStart()
    {
        return startPermitted;
    }
    public bool CanExecuteStop()
    {
        return stopPermitted;
    }
    public bool CanExecuteEnable()
    {
        return enablePermitted;
    }
    public bool CanExecuteDisable()
    {
        return disablePermitted;
    }
    public bool CanExecuteDelete()
    {
        return deletePermitted;
    }

    public void ExecuteStart()
    {
        currentJob curJob = ((currentJob)listviewCurrentJobs.SelectedItem);
        string curJobName = curJob.Name;
        if (new TaskService().GetFolder("DocuWare Notifications").Tasks[curJobName].Enabled == false)
            new TaskService().GetFolder("DocuWare Notifications").Tasks[curJobName].Enabled = true;
        new TaskService().GetFolder("DocuWare Notifications").Tasks[curJobName].Run();
        loadJobs();
    }
    public void ExecuteStop()
    {
        if (new TaskService().GetFolder("DocuWare Notifications").Tasks[((currentJob)listviewCurrentJobs.SelectedItem).Name].Enabled == true)
        {
            new TaskService().GetFolder("DocuWare Notifications").Tasks[((currentJob)listviewCurrentJobs.SelectedItem).Name].Stop();
            loadJobs();
        }
    }
    public void ExecuteEnable()
    {
        new TaskService().GetFolder("DocuWare Notifications").Tasks[((currentJob)listviewCurrentJobs.SelectedItem).Name].Enabled = true;
        loadJobs();
    }
    public void ExecuteDisable()
    {
        new TaskService().GetFolder("DocuWare Notifications").Tasks[((currentJob)listviewCurrentJobs.SelectedItem).Name].Enabled = false;
        loadJobs();
    }
    public void ExecuteDelete()
    {
        new TaskService().GetFolder("DocuWare Notifications").DeleteTask(((currentJob)listviewCurrentJobs.SelectedItem).Name);
        if (isMsSql)
        {
            mssqlconn.Open();
            new SqlCommand("DELETE FROM dbo.DocuWareNotifications WHERE NAME = '" + ((currentJob)listviewCurrentJobs.SelectedItem).Name + "'", mssqlconn).ExecuteNonQuery();
            mssqlconn.Close();
        }
        else
        {
            mysqlconn.Open();
            new MySqlCommand("DELETE FROM DocuWareNotifications WHERE NAME = '" + ((currentJob)listviewCurrentJobs.SelectedItem).Name + "'", mysqlconn).ExecuteNonQuery();
            mysqlconn.Close();
        }
        loadJobs();
    }
}

public partial class MonitoringWindow : MetroWindow
{
    [...]
    foreach (Task task in new TaskService().GetFolder("DocuWare Notifications").Tasks)
    {
        if (task != null)
        {
            currentJob item = new currentJob();
            switch (task.State)
            {
                case TaskState.Disabled:
                    item.State = "/DWNotDesigner;component/images/disabled.png";
                    item.Description = task.Name;
                    break;
                case TaskState.Ready:
                    item.State = "/DWNotDesigner;component/images/active.png";
                    item.Description = task.Name;
                    break;
                case TaskState.Running:
                    item.State = "/DWNotDesigner;component/images/working.png";
                    item.Description = task.Name;
                    break;
            }
            item.startPermitted = startPermitted;
            item.stopPermitted = stopPermitted;
            item.enablePermitted = enablePermitted;
            item.disablePermitted = disablePermitted;
            item.deletePermitted = deletePermitted;
            _jobCollection.Add(item);
        }
    }
}

for some reason there is no change!

解决方案

You could try using command bindings (you'll need prism):

...
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
    <MenuItem Command="{Binding StartCommand}"/>
    ...
</ContextMenu>
...

...

using Microsoft.Practices.Composite.Presentation.Commands;

public class currentJob
{
    public ICommand StartCommand {get; private set;}
    public currentJob ()
    {
         StartCommand = new DelegateCommand(ExecuteStart, CanExecuteStart); 
    }

    private bool CanExecuteStart()
    {
        //Determine whether start can be executed
        return true;
    }

    private void ExecuteStart()
    {
        //start here
    }
}

Here, ExecuteStart replaces startJob and CanExecuteStart replaces enablePermitted in the original example.


Edit It probably helps to explain why your original code does not work. Changes to bound properties are only picked up if a "PropertyChange" event is fired by the property's object. Implementing INotifyPropertyChanged would probably also fix your problem.


Edit An even more trivial problem with your original code is that it is binding to the wrong object - I presume no property startPermitted exists on FeedContextMenu (which anyway doesn't seem to be defined).


Edit There are still a few issues above: 1) the bindings are case-sensitive, so the binding should be {Binding StartCommand} etc. 2) You need to set the context menu on the individual items in the list. The following would work:

    <ListView Margin="10,10,10,55" Name="listviewCurrentJobs" ItemsSource="{Binding JobCollection}">
        <ListView.ItemTemplate>
                <DataTemplate>
                <Border BorderBrush="Black" BorderThickness="2">
                    <StackPanel Orientation="Horizontal" MinHeight="20" Background="White">
                        <StackPanel.ContextMenu>
                            <ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
                                <MenuItem Header="Starten" Command="{Binding Path=StartCommand}"/>
                                <MenuItem Header="Stoppen" Command="{Binding Path=StopCommand}"/>
                                <MenuItem Header="Aktivieren" Command="{Binding Path=EnableCommand}"/>
                                <MenuItem Header="Deaktivieren" Command="{Binding Path=DisableCommand}"/>
                                <MenuItem Header="Löschen" Command="{Binding Path=DeleteCommand}"/>
                            </ContextMenu>
                        </StackPanel.ContextMenu>
                        <Image Source="{Binding State}" Width="16"/>
                    </StackPanel>
                </Border>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

这篇关于WPF绑定到ListBox的ContextMenu的MenuItem中的IsEnabled属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆