[英]How to bind dependency property to DataGridComboBoxColumn in UserControl?
The XAML of my UserControl with name "Clinical_Protocol":我的用户控件的 XAML 名称为“Clinical_Protocol”:
<Grid>
<DataGrid Name="ClinicalProtocolDataGrid"
ItemsSource="{Binding DataGridItems, ElementName=Clinical_Protocol}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="Structure ID"
ItemsSource="{Binding ComboBoxItems, ElementName=Clinical_Protocol, Mode=TwoWay}"
SelectedItemBinding="{Binding SelectedStructureId, Mode=TwoWay}"
/>
<DataGridTextColumn Header="RT ROI Type Code"
Binding="{Binding RtRoiInterpretedTypeCode}"/>
<DataGridTextColumn Header="RT ROI Type Description"
Binding="{Binding RtRoiInterpretedTypeDescription}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
The dependency property for ItemsSource
of the DataGrid in the code behind:后面代码中DataGrid的ItemsSource
的依赖属性:
internal ObservableCollection<ClinicalProtocolDataGridItem> DataGridItems
{
get { return (ObservableCollection<ClinicalProtocolDataGridItem>)GetValue(DataGridItemsProperty); }
set { SetValue(DataGridItemsProperty, value); }
}
internal static readonly DependencyProperty DataGridItemsProperty =
DependencyProperty.Register("DataGridItems", typeof(ObservableCollection<ClinicalProtocolDataGridItem>),
typeof(ClinicalProtocolView), new PropertyMetadata(null, DataGridItemsPropertyChangedCallback));
private static void DataGridItemsPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (ClinicalProtocolView)d;
control.DataGridItems = (ObservableCollection<ClinicalProtocolDataGridItem>)e.NewValue;
}
The according ClinicalProtocolDataGridItem
class:根据ClinicalProtocolDataGridItem
class:
public class ClinicalProtocolDataGridItem
{
public string RtRoiInterpretedTypeCode { get; }
public string RtRoiInterpretedTypeDescription { get; }
public object SelectedStructureId { get; set; }
public ClinicalProtocolDataGridItem(string rtRoiInterpretedTypeCode, string rtRoiInterpretedTypeDescription)
{
RtRoiInterpretedTypeCode = rtRoiInterpretedTypeCode ??
throw new ArgumentNullException(nameof(rtRoiInterpretedTypeCode));
RtRoiInterpretedTypeDescription = rtRoiInterpretedTypeDescription ??
throw new ArgumentNullException(nameof(rtRoiInterpretedTypeDescription));
}
}
And finally the dependency property ComboBoxItems
:最后是依赖属性ComboBoxItems
:
public ObservableCollection<ComboBoxItem> ComboBoxItems
{
get { return (ObservableCollection<ComboBoxItem>)GetValue(ComboBoxItemsProperty); }
set { SetValue(ComboBoxItemsProperty, value); }
}
public static readonly DependencyProperty ComboBoxItemsProperty =
DependencyProperty.Register("ComboBoxItems", typeof(ObservableCollection<ComboBoxItem>),
typeof(ClinicalProtocolView), new PropertyMetadata(new ObservableCollection<ComboBoxItem>(),
PropertyChangedCallback));
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (ClinicalProtocolView)d;
control.ComboBoxItems = (ObservableCollection<ComboBoxItem>)e.NewValue;
}
I try to populate both dependency properties with the following:我尝试使用以下内容填充两个依赖属性:
private void AddSomeComboBoxItems()
{
ComboBoxItems = new ObservableCollection<ComboBoxItem>
{
new ComboBoxItem(){Content = "S1", HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center},
new ComboBoxItem(){Content = "S2", HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center},
new ComboBoxItem(){Content = "S3", HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center},
}
private void AddSomeRows()
{
var items = new List<ClinicalProtocolDataGridItem>
{
new ClinicalProtocolDataGridItem("PTV", "Description of PTV, and it is a very long description!"),
new ClinicalProtocolDataGridItem("OAR", "Description of OAR, and it is a very long description!"),
};
DataGridItems = new ObservableCollection<ClinicalProtocolDataGridItem>(items);
}
When I import it into a WPF application I get the following:当我将其导入 WPF 应用程序时,我得到以下信息:
And the error message: DataGridComboBoxColumn.ItemsSource IEnumerable Cannot find governing FrameworkElement or FrameworkContentElement for target element.
错误消息: DataGridComboBoxColumn.ItemsSource IEnumerable Cannot find governing FrameworkElement or FrameworkContentElement for target element.
Microsoft documentation says that it is possible to bind a collection of ComboBoxItem
. Microsoft 文档说可以绑定ComboBoxItem
的集合。 What am I missing?我错过了什么? I don't want to have a static resource, because the combo box items might change during runtime.我不想拥有 static 资源,因为组合框项目可能会在运行时发生变化。
The DataGridColumn is a simple DependencyObject, not a UI element. DataGridColumn 是一个简单的 DependencyObject,而不是 UI 元素。 It is not embedded in the visual tree and cannot get values from it.它没有嵌入到可视化树中,无法从中获取值。 The ElementName and FindAncestor bindings will not work in it. ElementName 和 FindAncestor 绑定在其中不起作用。
You need to get the collection into a static resource and only then get it from there for the DataGridColumn.您需要将集合放入 static 资源中,然后才从那里为 DataGridColumn 获取它。
<DataGrid Name="ClinicalProtocolDataGrid"
ItemsSource="{Binding DataGridItems, ElementName=Clinical_Protocol}"
AutoGenerateColumns="False">
<FrameworkElement.Resources>
<!--Using a CollectionViewSource as a proxy to create a "static link".-->
<CollectionViewSource
x:Key="comboBoxItems"
Source="{Binding ComboBoxItems, ElementName=Clinical_Protocol}"/>
</FrameworkElement.Resources>
<DataGrid.Columns>
<DataGridComboBoxColumn
Header="Structure ID"
ItemsSource="{Binding Source={StaticResource comboBoxItems}}"
SelectedItemBinding="{Binding SelectedStructureId, Mode=TwoWay}"/>
PS Please note my comment on your question. PS请注意我对你的问题的评论。 I explain there why even after a successful binding to such a source, the ComboBoxs may still work incorrectly.我在那里解释了为什么即使在成功绑定到这样的源之后,ComboBox 仍可能无法正常工作。
Remove dependency property ComboBoxItems
you don't need it, but add to the code behind a data provider method for your combo boxes:删除不需要的依赖属性ComboBoxItems
,但将其添加到组合框的数据提供程序方法背后的代码中:
public ObservableCollection<string> GetCbxSource()
{
return new ObservableCollection<string>
{
"S1",
"S2",
"S3",
};
}
Then in XAML you can declare a data provider and later use it like:然后在 XAML 中你可以声明一个数据提供者,然后像这样使用它:
<Grid>
<Grid.Resources>
<ObjectDataProvider x:Key="cbxData" MethodName="GetCbxSource" ObjectInstance="{x:Reference Clinical_Protocol}"/>
</Grid.Resources>
<DataGrid Name="ClinicalProtocolDataGrid"
ItemsSource="{Binding DataGridItems, ElementName=Clinical_Protocol}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="Structure ID"
ItemsSource="{Binding Source= {StaticResource cbxData}}"
SelectedItemBinding="{Binding SelectedStructureId, Mode=TwoWay}"
/>
<DataGridTextColumn Header="RT ROI Type Code"
Binding="{Binding RtRoiInterpretedTypeCode}"/>
<DataGridTextColumn Header="RT ROI Type Description"
Binding="{Binding RtRoiInterpretedTypeDescription}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.