WPF ComboBox Автоматический выбор, если только 1 элемент - PullRequest
3 голосов
/ 24 июня 2010

У меня есть поле со списком, которое я связываю с наблюдаемой коллекцией, которая изменяется (в зависимости от выбранной компании), и большое количество компаний будет иметь одну учетную запись (элементы), поэтому я хочу знать, каков наилучший способ сделайте так, чтобы ComboBox устанавливал SelectedItem, если в ItemsSource есть только 1 элемент, в противном случае оставьте его нулевым, чтобы гарантировать, что пользователь выберет учетную запись.

В настоящий момент я делаю это, проверяя коллекцию учетных записей каждый раз, когда она изменяется, и, если она содержит только одну, присваивая привязанному выбранному элементу свойства первый элемент в коллекции.

Это кажется запутанным, и мне нужно будет внедрить его в каждую модель представления отдельно и написать до 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;

Ответы [ 2 ]

6 голосов
/ 24 июня 2010

Должно быть довольно просто создать Присоединенное поведение , которое делает то, что вы хотите. Чтобы определить, когда коллекция Предметов в ComboBox изменилась, вам нужно использовать трюк, упомянутый в этом блоге .

Обновление : Вот мой пример (вам нужно добавить ссылку на 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>

4 голосов
/ 13 февраля 2014

Использование только 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>

Конечно, вы можете добавить ключ к этому стилю и использовать его по умолчанию для ComboBox, чтобы сделать его действительно полезным, но я надеюсь, что вы поняли идею.

...