我有一个组合框,我绑定到一个可观察的集合,它被更改(根据公司选择)和大量的公司将有一个帐户(项目)因此我想知道什么是最好的方法如果ItemsSource中只有1个项目,则让ComboBox设置SelectedItem,否则将其保留为null以确保用户选择一个帐户。
我现在这样做的方法是每次更改时检查帐户集合,如果它只包含一个,则将绑定的选定项目属性设置为集合中的第一个项目。
这看起来很冗长,我需要将它分别实现到每个视图模型中,并为每个组合框写入最多5行代码。
以下是我目前的代码,但我想知道是否可以通过扩展ComboBox控件来实现这一目的?如果有人对如何/从哪里开始有任何想法。
public CompanyGermanPower FromCompany
{
get { return _fromCompany; }
set
{
SetField(ref _fromCompany, value, () => FromCompany);
if(value!= null)
{
FromTradeAccountList = new ObservableCollection<TradeAccount>(TradeAccountAdapter.GetTradeAccounts(_session, value.ID));
if (Trade != null && FromTradeAccountList.Count == 1) Trade.TradeAccountFrom = FromTradeAccountList[0];
}
}
} private CompanyGermanPower _fromCompany;
答案 0 :(得分:6)
创建一个符合你想要的Attached Behaviour应该是相当简单的。要检测ComboBox中的Items集合何时发生更改,您需要使用此blog post中提到的技巧。
更新:这是我的抨击(您需要在项目中添加对System.Windows.Interactivity的引用 - 您可以从Expression Blend SDK中获取它):
using System.Windows.Interactivity;
public class SelectFirstItemComboBoxBehavior : Behavior<ComboBox>
{
protected override void OnAttached()
{
base.OnAttached();
(AssociatedObject.Items as INotifyCollectionChanged).CollectionChanged += HandleCollectionChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
(AssociatedObject.Items as INotifyCollectionChanged).CollectionChanged -= HandleCollectionChanged;
}
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (AssociatedObject.Items.Count == 1)
{
AssociatedObject.SelectedItem = AssociatedObject.Items.Cast<object>().First();
}
}
}
以下是您使用它的方式:
<Window x:Class="ComboBoxSelectFirstBehavior.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ComboBoxSelectFirstBehavior"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<x:Array x:Key="MyObjects" Type="{x:Type local:MyType}">
<local:MyType Name="WithChildren">
<local:MyType.Children>
<local:MyTypeCollection>
<local:MyType Name="Child1"/>
<local:MyType Name="Child2"/>
<local:MyType Name="Child3"/>
</local:MyTypeCollection>
</local:MyType.Children>
</local:MyType>
<local:MyType Name="WithOneChild">
<local:MyType.Children>
<local:MyTypeCollection>
<local:MyType Name="Child1"/>
</local:MyTypeCollection>
</local:MyType.Children>
</local:MyType>
<local:MyType Name="WithoutChildren">
<local:MyType.Children>
<local:MyTypeCollection>
</local:MyTypeCollection>
</local:MyType.Children>
</local:MyType>
</x:Array>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ComboBox x:Name="FirstCombo" Grid.Row="0" ItemsSource="{StaticResource MyObjects}" DisplayMemberPath="Name"/>
<ComboBox Grid.Row="1" ItemsSource="{Binding ElementName=FirstCombo, Path=SelectedItem.Children}" DisplayMemberPath="Name">
<i:Interaction.Behaviors>
<local:SelectFirstItemComboBoxBehavior/>
</i:Interaction.Behaviors>
</ComboBox>
</Grid>
答案 1 :(得分:4)
仅使用XAML:
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Items.Count, RelativeSource={RelativeSource Self}}" Value="1">
<Setter Property="SelectedIndex" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
当然,您可能希望为该样式添加一个键,并将其基于ComboBoxes的默认样式,以使其真正有用,但我希望您明白这一点。