WPF Binding to IsEnabled Property in ListBox' ContextMenu's MenuItem

最后都变了- 提交于 2019-12-13 08:44:02

问题


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!


回答1:


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>


来源:https://stackoverflow.com/questions/18270074/wpf-binding-to-isenabled-property-in-listbox-contextmenus-menuitem

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!