从 ListView 的 ItemContainer 设置 ContextMenu 的 DataContext?
我正在使用 mvvm 模式,并且很难弄清楚如何从 ListView 的 ItemContainerStyle 内部设置 ContextMenu 上的 DataContext。
我也不明白为什么 ListView.ContextMenu 和 ListView 的 GridView.ColumnHeaderContextMenu 可以从我的视图模型中看到属性和命令,但 ListView.ItemContainerStyle 内的 ContextMenu 却看不到。
错误
System.Windows.Data 错误:40:BindingExpression 路径错误:在“对象”“货币”(HashCode=43406546) 上找不到“AddMenuItem”属性。 BindingExpression:Path=AddMenuItem; DataItem='货币' (HashCode=43406546);目标元素是“ContextMenu”(名称=“”);目标属性是“ItemsSource”(类型“IEnumerable”)
View
<!-- 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;
}
}
}
ViewModel
[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
}
I am using the mvvm pattern and I am having a hard time figuring out how to set the DataContext on a ContextMenu from inside a ListView’s ItemContainerStyle.
I also do not understand why the ListView.ContextMenu and the ListView’s GridView.ColumnHeaderContextMenu can see the properties and commands from my view model, but the ContextMenu inside the ListView.ItemContainerStyle cannot.
Error
System.Windows.Data Error: 40 : BindingExpression path error: 'AddMenuItem' property not found on 'object' ''Currency' (HashCode=43406546)'. BindingExpression:Path=AddMenuItem; DataItem='Currency' (HashCode=43406546); target element is 'ContextMenu' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
View
<!-- 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>
Code Behind
[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;
}
}
}
ViewModel
[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
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这个问题帮助我弄清楚了。
WPF MenuItem.Command 绑定到 ElementName 结果到 System.Windows.Data 错误:4:找不到与引用绑定的源
我为其他遇到此问题的人更新了源。
为了快速参考,这就是我所做的。
添加 Josh Smith 的 ElementSpy 类。 使用 ElementSpy 启用 ElementName 绑定
添加 ElementSpy到 UserControl 的资源。
然后绑定到资源并使用 Element 属性绑定到 DataContext 和您选择的属性。
This question helped me figure it out.
WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4 : Cannot find source for binding with reference
I updated the source for anyone else that is having this issue.
For quick reference this is what I did.
Add Josh Smith's ElementSpy class. Enable ElementName Bindings with ElementSpy
Add ElementSpy to the UserControl’s rsources.
Then bind to the resource and use the Element property to bind to the DataContext and the property that you choose.
您必须在绑定中使用RelativeSource 和 PlacementTarget。我使用以下 xaml 添加上下文菜单来设置数据网格列的可见性。
you have to use RelativeSource and PlacementTarget in your binding. i use the following xaml to add a contextmenu to set visibility of datagrid columns.