【问题标题】:WPF Binding to IsEnabled Property in ListBox' ContextMenu's MenuItemWPF 绑定到 ListBox 的 ContextMenu 的 MenuItem 中的 IsEnabled 属性
【发布时间】:2013-08-16 09:27:04
【问题描述】:

我正在查看有关数据绑定到上下文菜单的其他线程,但我无法弄清楚如何让它工作,因为建议/答案对我不起作用。

我有一个列表框,它绑定到 ObversableCollection - 工作正常。

现在我在该列表框中有一个上下文菜单。该上下文菜单有 4 个项目来激活、停用等所选任务(这是列表框中表示的项目)。

由于权限,我需要控制上下文菜单中的项目是启用还是禁用,因此我必须通过将 ContextMenuItem 的 IsEnabled-Property 绑定到 Listbox 绑定到的同一个集合来设置它。

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


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

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);
        }
    }
}

由于某种原因没有变化!

【问题讨论】:

    标签: wpf isenabled


    【解决方案1】:

    您可以尝试使用命令绑定(您需要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
        }
    }
    

    这里,ExecuteStart 替换了原始示例中的 startJobCanExecuteStart 替换了 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>
    

    【讨论】:

    • 这不会禁用按钮吧?
    • 如果 CanExecuteStart 返回 false,则按钮将被禁用
    • 我现在已经更新了这个问题,到现在还不行。
    • 查看对 ContextMenu DataContext 绑定的编辑。你第一次就快到了!
    • 遗憾的是它仍然无法正常工作,DelegateCommand 的 isActive 属性被设置为 false,这可能是个问题吗?我还看到互联网上的人试图手动调用 CanExecuteStart() 方法,我没有这样做 - 这是正确的方法吗?
    猜你喜欢
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 2017-07-22
    • 2016-10-18
    相关资源
    最近更新 更多