c# - WPF ComboBox Selección automática si solo 1 elemento
mvvm controls (2)
Tengo un cuadro combinado que vinculo a una colección observable, que cambia (de acuerdo con la empresa seleccionada) y un gran número de empresas tendrá una sola cuenta (los elementos), por lo tanto, quiero saber cuál es la mejor manera de hacer el ComboBox establezca SelectedItem si solo hay 1 elemento en ItemsSource, de lo contrario, deje el valor nulo para garantizar que el usuario elija una cuenta.
La forma en que estoy haciendo esto en este momento es verificando la colección de cuentas cada vez que se cambia, y si contiene solo una, estableciendo la propiedad del elemento seleccionado como vinculado al primer elemento de la colección.
Esto parece largo aliento y tendría que implementarlo en cada modelo de vista por separado y escribir hasta 5 líneas de código para cada cuadro combinado.
El siguiente es el código que actualmente, pero me preguntaba si sería posible lograr esto al extender el control ComboBox. Y si alguien tiene alguna idea sobre cómo / dónde comenzar.
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;
Debe ser bastante sencillo crear un comportamiento adjunto que haga lo que desee. Para detectar cuándo cambió la colección de Elementos en el ComboBox, necesitarías usar el truco mencionado en esta publicación de blog .
Actualización : Aquí está mi puñalada (tendrá que agregar una referencia a System.Windows.Interactivity a su proyecto; puede obtenerlo desde 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();
}
}
}
Así es como lo usa:
<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>
Usando solo 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>
Por supuesto, es posible que desee agregar una clave a ese estilo y basarlo en el estilo predeterminado para ComboBoxes para que sea realmente útil, pero espero que entienda la idea.