自定义用户控件与包含 DataTemplate 的 ComboBox 的 WPF 绑定
WPF Bindings of a Custom User Control with a ComboBox containing a DataTemplate
我正在尝试创建一个带有 ListView 的自定义用户控件,其中包含如下所示的数据模板:
<ComboBox ItemsSource="{Binding ItemsSource, ElementName=root}"
SelectedItem="{Binding SelectedItem, ElementName=root, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!-- This is what I tried:
Working but not what I want <TextBox Text="{Binding Name}"/>
Returns the List only the word "FallBack" <TextBox Text="{Binding ItemText, ElementName=root}" />
Returns the LIst empty <TextBox Text="{Binding ItemText}" />
-->
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
在后面的代码中,我为这种情况创建了必要的依赖属性(所以我假设)唯一相关的是关于项目文本,它看起来像这样:
#region ItemText
public string ItemText
{
get { return (string)GetValue(ItemTextProperty); }
set { SetValue(ItemTextProperty, value); }
}
// Using a DependencyProperty as the backing store for ItemText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemTextProperty =
DependencyProperty.Register("ItemText", typeof(string), typeof(CardComboBox), new PropertyMetadata("FallBack"));
#endregion
我想做的是像那样添加用户控件
<local:CardComboBox ItemsSource="{Binding Persons}" SelectedItem="{Binding SelectedPerson}" ItemText="{Binding Name}" IsEnabled="True" />
选项一:
<TextBox Text="{Binding Name}"/>
工作正常,因为 Class Person 的 PropertyName 是 Name,但我显然不想对其进行硬编码。我想将它绑定到我喜欢的 属性。
选项 2:
<TextBox Text="{Binding ItemText, ElementName=root}" />
为我提供了 7 个项目的列表(根据列表),但由于 DependencyPropertyMetadata 只显示“Fallback”一词。
选项 3:
<TextBox Text="{Binding ItemText}" />
给我列表,但没有任何文字。
我也尝试使用 relativeSource,但结果相似。
#region Person
Person _selectedPerson;
public Person SelectedPerson
{
get => _selectedPerson;
set
{
if (value != _selectedPerson)
{
_selectedPerson = value;
OnPropertyChanged("SelectedPerson");
}
}
}
ObservableCollection<Person> _persons;
public ObservableCollection<Person> Persons
{
get => _persons;
set
{
if (value != _persons)
{
_persons = value;
OnPropertyChanged("Persons");
}
}
}
public void populatePersons()
{
Persons = new ObservableCollection<Person>();
Persons.Add(new Person("Carl"));
Persons.Add(new Person("Max"));
Persons.Add(new Person("May"));
Persons.Add(new Person("Jen"));
Persons.Add(new Person("Charly"));
Persons.Add(new Person("Nora"));
Persons.Add(new Person("Yvonne"));
}
#endregion
我已经添加了我要绑定的列表。在 ViewModel 的构造函数中调用方法 Populate Persons。
<TextBox Text="{Binding ItemText, RelativeSource={RelativeSource AncestorType=local:CardComboBox}}" />
会将 TextBox
绑定到父 CardComboBox
的 ItemText
依赖项 属性 的当前值,如果这是您想要的。
但是,如果您想显示每个 Person
字节的 Name
属性 的值,您还希望能够指定 属性 的名称Person
要使用您的 ItemText
属性 进行绑定,您必须以编程方式创建绑定。
目前最接近的解决方案是公开 ItemContentTemplate 依赖项 属性,然后将其绑定到静态资源(例如来自 App.xaml)
UserControl 的 XAML 如下所示:
<StackPanel Style="{StaticResource CardStackPanel}" Orientation="{Binding Orientation, ElementName=root}" >
<Label x:Name="Label" Content="{Binding TitleText, ElementName=root}"/>
<ComboBox ItemsSource ="{Binding ItemsSource, RelativeSource={RelativeSource AncestorType=UserControl}}"
ItemTemplate="{Binding ItemContentTemplate, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay}" />
</StackPanel>
ComboBox 部分的隐藏代码:
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CardComboBox));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(CardComboBox));
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public DataTemplate ItemContentTemplate
{
get { return (DataTemplate)GetValue(ItemContentTemplateProperty); }
set { SetValue(ItemContentTemplateProperty, value); }
}
public static readonly DependencyProperty ItemContentTemplateProperty =
DependencyProperty.Register("ItemContentTemplate", typeof(DataTemplate), typeof(CardComboBox));
App.xaml中的静态资源(示例):
<DataTemplate x:Key="FirstNamesTemplate">
<Label Content="{Binding FirstName}"/>
</DataTemplate>
ComboBoxCard 的实现现在看起来像这样:
<local:CardComboBox ItemsSource="{Binding PersonModels}" SelectedItem="{Binding SelectedPersonModel, Mode=TwoWay}" ItemContentTemplate="{StaticResource FirstNamesTemplate}" TitleText="With StaticResource" IsEnabled="False"/>
此模式允许在自定义用户控件中实现组合框或列表视图。
我正在尝试创建一个带有 ListView 的自定义用户控件,其中包含如下所示的数据模板:
<ComboBox ItemsSource="{Binding ItemsSource, ElementName=root}"
SelectedItem="{Binding SelectedItem, ElementName=root, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!-- This is what I tried:
Working but not what I want <TextBox Text="{Binding Name}"/>
Returns the List only the word "FallBack" <TextBox Text="{Binding ItemText, ElementName=root}" />
Returns the LIst empty <TextBox Text="{Binding ItemText}" />
-->
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
在后面的代码中,我为这种情况创建了必要的依赖属性(所以我假设)唯一相关的是关于项目文本,它看起来像这样:
#region ItemText
public string ItemText
{
get { return (string)GetValue(ItemTextProperty); }
set { SetValue(ItemTextProperty, value); }
}
// Using a DependencyProperty as the backing store for ItemText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemTextProperty =
DependencyProperty.Register("ItemText", typeof(string), typeof(CardComboBox), new PropertyMetadata("FallBack"));
#endregion
我想做的是像那样添加用户控件
<local:CardComboBox ItemsSource="{Binding Persons}" SelectedItem="{Binding SelectedPerson}" ItemText="{Binding Name}" IsEnabled="True" />
选项一:
<TextBox Text="{Binding Name}"/>
工作正常,因为 Class Person 的 PropertyName 是 Name,但我显然不想对其进行硬编码。我想将它绑定到我喜欢的 属性。
选项 2:
<TextBox Text="{Binding ItemText, ElementName=root}" />
为我提供了 7 个项目的列表(根据列表),但由于 DependencyPropertyMetadata 只显示“Fallback”一词。
选项 3:
<TextBox Text="{Binding ItemText}" />
给我列表,但没有任何文字。
我也尝试使用 relativeSource,但结果相似。
#region Person
Person _selectedPerson;
public Person SelectedPerson
{
get => _selectedPerson;
set
{
if (value != _selectedPerson)
{
_selectedPerson = value;
OnPropertyChanged("SelectedPerson");
}
}
}
ObservableCollection<Person> _persons;
public ObservableCollection<Person> Persons
{
get => _persons;
set
{
if (value != _persons)
{
_persons = value;
OnPropertyChanged("Persons");
}
}
}
public void populatePersons()
{
Persons = new ObservableCollection<Person>();
Persons.Add(new Person("Carl"));
Persons.Add(new Person("Max"));
Persons.Add(new Person("May"));
Persons.Add(new Person("Jen"));
Persons.Add(new Person("Charly"));
Persons.Add(new Person("Nora"));
Persons.Add(new Person("Yvonne"));
}
#endregion
我已经添加了我要绑定的列表。在 ViewModel 的构造函数中调用方法 Populate Persons。
<TextBox Text="{Binding ItemText, RelativeSource={RelativeSource AncestorType=local:CardComboBox}}" />
会将 TextBox
绑定到父 CardComboBox
的 ItemText
依赖项 属性 的当前值,如果这是您想要的。
但是,如果您想显示每个 Person
字节的 Name
属性 的值,您还希望能够指定 属性 的名称Person
要使用您的 ItemText
属性 进行绑定,您必须以编程方式创建绑定。
目前最接近的解决方案是公开 ItemContentTemplate 依赖项 属性,然后将其绑定到静态资源(例如来自 App.xaml)
UserControl 的 XAML 如下所示:
<StackPanel Style="{StaticResource CardStackPanel}" Orientation="{Binding Orientation, ElementName=root}" >
<Label x:Name="Label" Content="{Binding TitleText, ElementName=root}"/>
<ComboBox ItemsSource ="{Binding ItemsSource, RelativeSource={RelativeSource AncestorType=UserControl}}"
ItemTemplate="{Binding ItemContentTemplate, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay}" />
</StackPanel>
ComboBox 部分的隐藏代码:
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CardComboBox));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(CardComboBox));
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public DataTemplate ItemContentTemplate
{
get { return (DataTemplate)GetValue(ItemContentTemplateProperty); }
set { SetValue(ItemContentTemplateProperty, value); }
}
public static readonly DependencyProperty ItemContentTemplateProperty =
DependencyProperty.Register("ItemContentTemplate", typeof(DataTemplate), typeof(CardComboBox));
App.xaml中的静态资源(示例):
<DataTemplate x:Key="FirstNamesTemplate">
<Label Content="{Binding FirstName}"/>
</DataTemplate>
ComboBoxCard 的实现现在看起来像这样:
<local:CardComboBox ItemsSource="{Binding PersonModels}" SelectedItem="{Binding SelectedPersonModel, Mode=TwoWay}" ItemContentTemplate="{StaticResource FirstNamesTemplate}" TitleText="With StaticResource" IsEnabled="False"/>
此模式允许在自定义用户控件中实现组合框或列表视图。