wpf - 从 ListView 的 ItemContainer 为 ContextMenu 设置 DataContext?

标签 wpf xaml listview binding

我正在使用 mvvm 模式,我很难从 ListView 的 ItemContainerStyle 中弄清楚如何在 ContextMenu 上设置 DataContext。

我也不明白为什么 ListView.ContextMenu 和 ListView 的 GridView.ColumnHeaderContextMenu 可以从我的 View 模型中看到属性和命令,但 ListView.ItemContainerStyle 中的 ContextMenu 却不能。

错误

System.Windows.Data 错误:40:BindingExpression 路径错误:在“对象”“货币”(HashCode = 43406546)上找不到“AddMenuItem”属性。绑定(bind)表达式:路径=添加菜单项; DataItem='货币' (HashCode=43406546);目标元素是'ContextMenu'(名称='');目标属性是“ItemsSource”(类型“IEnumerable”)

查看

<!-- Removed styles for clarity. -->
<UserControl>

<!-- Add ElementSpy to the UserControl’s rsources -->
<UserControl.Resources>
    <framework:ElementSpy x:Key="spy" />
</UserControl.Resources>

<ListView ItemsSource="{Binding Currency}">

    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <!-- 'AddMenuItem' property not found on 'object' 'Currency' -->
                    <!-- ContextMenu ItemsSource="{Binding AddMenuItem}" / -->

                    <!-- Use the ElementSpy resource -->
                    <ContextMenu ItemsSource="{Binding Source={StaticResource spy}, Path=Element.DataContext.AddMenuItem}" />
                </Setter.Value>
            </Setter>
        </Style>
    </ListView.ItemContainerStyle>

    <ListView.ContextMenu>
        <!-- Works -->
        <ContextMenu ItemsSource="{Binding EditMenuItem}" />
    </ListView.ContextMenu>

    <ListView.View>
        <GridView>
            <GridView.ColumnHeaderContextMenu>
                <!-- Works -->
                <ContextMenu ItemsSource="{Binding SortMenuItem}" />
            </GridView.ColumnHeaderContextMenu>

            <GridViewColumn Header="Code"
                            DisplayMemberBinding="{Binding Path=Code}" />

            <GridViewColumn Header="Description"
                            DisplayMemberBinding="{Binding Path=Description}" />

            <GridViewColumn Header="Exchange Rate"
                            DisplayMemberBinding="{Binding Path=ExchangeRate}" />
        </GridView>

    </ListView.View>

</ListView>
</UserControl>

后面的代码
[Export(ViewNames.CurrencyMasterView, typeof(IMasterView))]
[PartCreationPolicy(CreationPolicy.Shared)]
public partial class CurrencyMasterView
    : UserControl, IMasterView
{
    public CurrencyMasterView()
    {
        InitializeComponent();
    }

    [Import]
    private MasterViewModel ViewModel
    {
        set
        {
            this.DataContext = value;
        }
    }
}

查看型号
[Export(typeof(MasterViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class MasterViewModel
    : ViewModelBase
{
    [ImportingConstructor]
    public MasterViewModel(IGeneralController generalController, IRegionManager regionManager)
    {
    }

    public ObservableCollection<Currency> Currency
    {
        get
        {
            return this.currency;
        }

        set
        {
            if (this.currency != value)
            {
                this.currency = value;
                this.RaisePropertyChanged(() => this.Currency);
            }
        }
    }

    public List<MenuItemMvvm> SortMenuItem
    {
        get
        {
            return this.CreateSortMenuItem();
        }
    }

    public List<MenuItemMvvm> EditMenuItem
    {
        get
        {
            return this.CreateEditMenuItem();
        }
    }

    public List<MenuItemMvvm> AddMenuItem
    {
        get
        {
            return this.CreateAddMenuItem();
        }
    }

    private List<MenuItemMvvm> CreateEditMenuItem()
    {
        var menu = new List<MenuItemMvvm>();

        menu.Add(new MenuItemMvvm("_Edit")
        {
            Command = this.EditCommand,
            Icon = new Image
            {
                Source = new BitmapImage(new Uri("pack://application:,,,/POS.Modules.Core;component/Resources/Images/16X16/Edit.png"))
            }
        });

        menu.Add(new MenuItemMvvm("_Duplicate")
        {
            Command = this.DuplicateCommand,
            Icon = new Image
            {
                Source = new BitmapImage(new Uri("pack://application:,,,/POS.Modules.Core;component/Resources/Images/16X16/Copy.png"))
            }
        });

        menu.Add(new MenuItemMvvm("_Delete")
        {
            Command = this.DeleteCommand,
            Icon = new Image
            {
                Source = new BitmapImage(new Uri("pack://application:,,,/POS.Modules.Core;component/Resources/Images/16X16/Delete.png"))
            }
        });


        return menu;
    }

    // Other methods removed for clarity
}

最佳答案

这个问题帮助我弄清楚了。
WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4 : Cannot find source for binding with reference

我为其他遇到此问题的人更新了源代码。

为了快速引用,这就是我所做的。

添加 Josh Smith 的 ElementSpy 类。 Enable ElementName Bindings with ElementSpy

将 ElementSpy 添加到 UserControl 的 rsources。

<UserControl.Resources>
    <framework:ElementSpy x:Key="spy" />
</UserControl.Resources>

然后绑定(bind)到资源并使用 Element 属性绑定(bind)到 DataContext 和您选择的属性。
<ContextMenu ItemsSource="{Binding Source={StaticResource spy}, Path=Element.DataContext.AddMenuItem}" />

关于wpf - 从 ListView 的 ItemContainer 为 ContextMenu 设置 DataContext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5545370/

相关文章:

c# - 将 System.Windows.Input.KeyEventArgs 键转换为 char

c# - InitializeComponent() 有什么作用,它在 WPF 中是如何工作的?

c# - WPF 列表框布局 : multiple columns

wpf - 如何在 xaml 字符串中使用 "{"符号

wpf - ViewModel 构造函数包含 WPF 中的参数

android - android listview中的标准文本和图像大小

android - 如何跳过listview的getView中的特定行

c# - WPF win8平板电脑模式键盘隐藏屏幕底部的项目

c# - 如何访问 WPF 层次结构中对象的基本父级?

.net - WPF - 如何从 ListView 中清除选择?