【问题标题】:WPF ComboBox Auto Select If Only 1 ItemWPF ComboBox 自动选择如果只有 1 个项目
【发布时间】:2011-03-07 17:52:59
【问题描述】:

我有一个组合框,我绑定到一个可观察的集合,它会发生变化(根据选择的公司)并且大量公司将有一个帐户(项目)因此我想知道最好的方法是什么如果 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;

【问题讨论】:

    标签: c# wpf mvvm controls combobox


    【解决方案1】:

    创建一个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>
    

    【讨论】:

    • 谢谢你,这会是五次吗:) 看起来很有希望
    • 工作得非常好,希望我能多次投票!很好的解释和代码!
    【解决方案2】:

    仅使用 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 的默认样式,以使其真正有用,但我希望您明白这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-28
      • 2016-01-17
      • 1970-01-01
      • 1970-01-01
      • 2014-07-02
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      相关资源
      最近更新 更多