带有两个项目源的组合框
Combobox with two itemssources
我正在尝试根据单选按钮列出客户或供应商的列表。当我将一个列表绑定到一个组合框时,它就起作用了。当我尝试使用数据触发器动态更改要显示的集合时,没有任何反应。
由于单独的列表与不变的组合框一起工作,我已经知道这不是数据上下文类型的问题。我还安装了 Fody Weaver 来自动生成 INotifyProperties。
XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<RadioButton Content="Klant"
Grid.Column="0"
Foreground="White"
Margin="10"
IsChecked="{Binding ButtonCustomerIsChecked}"
GroupName="CustomerSupplier"
Name="RadioButtonCustomer"
/>
<RadioButton Content="Leverancier"
Grid.Column="1"
Foreground="White"
Margin="10"
IsChecked="{Binding ButtonSupplierIsChecked}"
GroupName="CustomerSupplier"
Name="RadioButtonSupplier"
/>
</Grid>
<ComboBox ItemsSource="{Binding SupplierList}"
DisplayMemberPath="Name"
SelectedItem="{Binding Path=SelectedCustomerSupplier}"
Style="{StaticResource InputComboBox}"
/>
<ComboBox Style="{StaticResource InputComboBox}"
ItemsSource="{Binding}"
DisplayMemberPath="Name"
>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=ButtonCustomerIsChecked, diag:PresentationTraceSources.TraceLevel=High}" Value="True">
<Setter Property="ItemsSource" Value="{Binding CustomerList}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=ButtonSupplierIsChecked, diag:PresentationTraceSources.TraceLevel=High}" Value="True">
<Setter Property="ItemsSource" Value="{Binding SupplierList}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox>
C#(ViewModel):
CustomerList = new ObservableCollection<Customer>
{
new Customer{Id=1, Name="Bart"},
new Customer{Id=1, Name="Nick"},
new Customer{Id=1, Name="Erwin"},
};
SupplierList = new ObservableCollection<Customer>
{
new Customer{Id=1, Name="Rita"},
new Customer{Id=1, Name="Sascha"},
new Customer{Id=1, Name="Didier"},
};
更多 C#(客户 class):
public class Customer : IStakeholder
{
/// <summary>
/// The ID of the customer
/// </summary>
public int Id { get; set; }
/// <summary>
/// The name of the customer
/// </summary>
public string Name { get; set; }
/// <summary>
/// The phone number
/// </summary>
public string PhNr { get; set; }
/// <summary>
/// The VAT number
/// can be null
/// </summary>
public string VatNr { get; set; }
/// <summary>
/// The country where the customer is located
/// </summary>
public CountryCat CountryCat { get; set; }
/// <summary>
/// A list of payments made by the customer
/// </summary>
public List<IPayments> Payments { get; set; }
}
而不是
<ComboBox ItemsSource="{Binding SupplierList}" ...>
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<DataTrigger ...>
<Setter Property="ItemsSource" Value="{Binding CustomerList}"/>
</DataTrigger>
</Style.Triggers>
<Style>
<ComboBox.Style>
</ComboBox>
您必须像这样将 ItemsSource
的初始分配移动到样式设置器中:
<ComboBox ...>
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Setters>
<Setter Property="ItemsSource" Value="{Binding SupplierList}" />
</Style.Setters>
<Style.Triggers>
<DataTrigger ...>
<Setter Property="ItemsSource" Value="{Binding CustomerList}"/>
</DataTrigger>
</Style.Triggers>
<Style>
<ComboBox.Style>
</ComboBox>
否则样式触发器无法覆盖本地值,参见dependency property value precedence。
另一个问题是您在视图中绑定到特定元素的样式,这使得它的可重用性降低,您会看到必须创建尽可能多的数据触发器你有单选按钮。另外,您在那里的绑定中使用了错误的 ElementName
,例如不是 ButtonCustomerIsChecked
,应该是 RadioButtonCustomer
(供应商也一样)。
这是一个修复方法,您只需要一个触发器:
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=RadioButtonCustomer}" Value="True">
<Setter Property="ItemsSource" Value="{Binding CustomerList}"/>
</DataTrigger>
</Style.Triggers>
更好的方法是在 ViewModel 中提供一个 属性(这是 MVVM 术语,viewmodel 是一个 class,您定义了 CustomerList
),它将用于 运行触发。
或者更简单的方法是在视图模型中更改绑定到 ItemsSource
的单个 属性,这样您就不需要视图中的触发器。
我正在尝试根据单选按钮列出客户或供应商的列表。当我将一个列表绑定到一个组合框时,它就起作用了。当我尝试使用数据触发器动态更改要显示的集合时,没有任何反应。
由于单独的列表与不变的组合框一起工作,我已经知道这不是数据上下文类型的问题。我还安装了 Fody Weaver 来自动生成 INotifyProperties。
XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<RadioButton Content="Klant"
Grid.Column="0"
Foreground="White"
Margin="10"
IsChecked="{Binding ButtonCustomerIsChecked}"
GroupName="CustomerSupplier"
Name="RadioButtonCustomer"
/>
<RadioButton Content="Leverancier"
Grid.Column="1"
Foreground="White"
Margin="10"
IsChecked="{Binding ButtonSupplierIsChecked}"
GroupName="CustomerSupplier"
Name="RadioButtonSupplier"
/>
</Grid>
<ComboBox ItemsSource="{Binding SupplierList}"
DisplayMemberPath="Name"
SelectedItem="{Binding Path=SelectedCustomerSupplier}"
Style="{StaticResource InputComboBox}"
/>
<ComboBox Style="{StaticResource InputComboBox}"
ItemsSource="{Binding}"
DisplayMemberPath="Name"
>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=ButtonCustomerIsChecked, diag:PresentationTraceSources.TraceLevel=High}" Value="True">
<Setter Property="ItemsSource" Value="{Binding CustomerList}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=ButtonSupplierIsChecked, diag:PresentationTraceSources.TraceLevel=High}" Value="True">
<Setter Property="ItemsSource" Value="{Binding SupplierList}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox>
C#(ViewModel):
CustomerList = new ObservableCollection<Customer>
{
new Customer{Id=1, Name="Bart"},
new Customer{Id=1, Name="Nick"},
new Customer{Id=1, Name="Erwin"},
};
SupplierList = new ObservableCollection<Customer>
{
new Customer{Id=1, Name="Rita"},
new Customer{Id=1, Name="Sascha"},
new Customer{Id=1, Name="Didier"},
};
更多 C#(客户 class):
public class Customer : IStakeholder
{
/// <summary>
/// The ID of the customer
/// </summary>
public int Id { get; set; }
/// <summary>
/// The name of the customer
/// </summary>
public string Name { get; set; }
/// <summary>
/// The phone number
/// </summary>
public string PhNr { get; set; }
/// <summary>
/// The VAT number
/// can be null
/// </summary>
public string VatNr { get; set; }
/// <summary>
/// The country where the customer is located
/// </summary>
public CountryCat CountryCat { get; set; }
/// <summary>
/// A list of payments made by the customer
/// </summary>
public List<IPayments> Payments { get; set; }
}
而不是
<ComboBox ItemsSource="{Binding SupplierList}" ...>
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<DataTrigger ...>
<Setter Property="ItemsSource" Value="{Binding CustomerList}"/>
</DataTrigger>
</Style.Triggers>
<Style>
<ComboBox.Style>
</ComboBox>
您必须像这样将 ItemsSource
的初始分配移动到样式设置器中:
<ComboBox ...>
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Setters>
<Setter Property="ItemsSource" Value="{Binding SupplierList}" />
</Style.Setters>
<Style.Triggers>
<DataTrigger ...>
<Setter Property="ItemsSource" Value="{Binding CustomerList}"/>
</DataTrigger>
</Style.Triggers>
<Style>
<ComboBox.Style>
</ComboBox>
否则样式触发器无法覆盖本地值,参见dependency property value precedence。
另一个问题是您在视图中绑定到特定元素的样式,这使得它的可重用性降低,您会看到必须创建尽可能多的数据触发器你有单选按钮。另外,您在那里的绑定中使用了错误的 ElementName
,例如不是 ButtonCustomerIsChecked
,应该是 RadioButtonCustomer
(供应商也一样)。
这是一个修复方法,您只需要一个触发器:
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=RadioButtonCustomer}" Value="True">
<Setter Property="ItemsSource" Value="{Binding CustomerList}"/>
</DataTrigger>
</Style.Triggers>
更好的方法是在 ViewModel 中提供一个 属性(这是 MVVM 术语,viewmodel 是一个 class,您定义了 CustomerList
),它将用于 运行触发。
或者更简单的方法是在视图模型中更改绑定到 ItemsSource
的单个 属性,这样您就不需要视图中的触发器。