WPF / XAML绑定:使用实际的DataContext [英] WPF/XAML Binding: Work with real DataContext
问题描述
这是我的XAML代码:
This is my XAML code:
<ComboBox Grid.Row="0" Margin="5" ItemsSource="{Binding Path=Clvm.Categories}">
</ComboBox>
<GridSplitter Grid.Row="0" Height="3" />
<DataGrid Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding Alvm.Artists}">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" IsReadOnly="True" Binding="{Binding Id}" />
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Email" Binding="{Binding Email}" />
<DataGridComboBoxColumn Header="Category" SelectedItemBinding="{Binding Category}"
ItemsSource="{Binding Path=Clvm.Categories}" />
</DataGrid.Columns>
</DataGrid>
上面的ComboBox仅用于测试-我想看看是否可以显示所有类别及其内容效果很好。
The ComboBox above is just for testing - I want to see if I can display all my Categories and it works well.
下面的DataGrid是我真正想要的控件。我希望将该Category ComboBox作为DataGrid的一列。但是我在代码段中执行此操作的方式显然不起作用,因为列的数据绑定是相对于DataGrid的ItemsSource而不是相对于旧DataContext的。
The DataGrid below is the control I really want. I want that Categories ComboBox as a column of the DataGrid. But the way I do it in the snippet obviously doesn't work as the data bindings for the columns are relative to the DataGrid's ItemsSource and not to the old DataContext. How can I switch it back for that binding?
控制类:
public partial class ArtistManagementControl : UserControl {
public ArtistManagementControl() {
InitializeComponent();
IDatabase db = new MYSQLDatabase("Server = localhost; Database = ufo; Uid = root;");
SharedServices.Init(db);
Alvm = new ArtistListViewModel(SharedServices.GetInstance().ArtistService, SharedServices.GetInstance().CategoryService);
Clvm = new CategoryListViewModel(SharedServices.GetInstance().CategoryService);
this.DataContext = this;
}
public ArtistListViewModel Alvm {
get; private set;
}
public CategoryListViewModel Clvm {
get; private set;
}
}
类别的ViewModel:
The ViewModel for the categories:
public class CategoryListViewModel {
private ICategoryService categoryService;
public CategoryListViewModel(ICategoryService categoryService) {
this.categoryService = categoryService;
Categories = new ObservableCollection<CategoryViewModel>();
UpdateCategories();
}
public ObservableCollection<CategoryViewModel> Categories {
get; set;
}
public void UpdateCategories() {
Categories.Clear();
foreach(var cat in categoryService.GetAllCategories()) {
Categories.Add(new CategoryViewModel(cat));
}
}
}
推荐答案
由于 DataGridComboBoxColumn
或任何其他受支持的数据网格列都不属于 datagrid
可视树的一部分,因此它们不会不会继承 datagrid
的 DataContext
。由于它们不位于可视树中,因此使用 RelativeSource
获取 DataContext
的任何尝试均将无效。
Since DataGridComboBoxColumn
or any other supported data grid columns are not part of visual tree of datagrid
so they don't inherit the DataContext
of datagrid
. Since, they don't lie in visual tree so any try to get DataContext
using RelativeSource
won't work.
解决方案-您可以创建一个代理元素来绑定window的数据上下文;使用该代理元素绑定 DataGridComboBoxColumn
的 ItemsSource
。
Solution - You can create a proxy element to bind the data context of window; use that proxy element to bind the ItemsSource
of DataGridComboBoxColumn
.
<Grid>
<Grid.Resources>
<FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
</Grid.Resources>
<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"></ContentControl>
<DataGrid x:Name="datagrid" Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding Alvm.Artists}">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" IsReadOnly="True" Binding="{Binding Id}" />
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Email" Binding="{Binding Email}" />
<DataGridComboBoxColumn Header="Category" SelectedItemBinding="{Binding Category}"
ItemsSource="{Binding DataContext.Clvm.Categories, Source={StaticResource ProxyElement}}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
这篇关于WPF / XAML绑定:使用实际的DataContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!