【问题标题】:Can I disable the first item a WPF combobox within xaml code?我可以在 xaml 代码中禁用 WPF 组合框的第一项吗?
【发布时间】:2019-09-15 22:01:14
【问题描述】:

考虑以下组合框:

<ComboBox ItemsSource="{Binding Presets.VolumePresetList}" SelectedIndex="{Binding VolumePresetSelectedIndex, UpdateSourceTrigger=PropertyChanged}" Margin="10, 10" HorizontalAlignment="Left"
            MinWidth="150">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding PresetName, UpdateSourceTrigger=Explicit}" VerticalAlignment="Center" Height="20" BorderThickness="0" LostFocus="TextBox_LostFocus" KeyUp="TextBox_KeyUp"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

组合框的第一个项目是默认预设,在文本框中具有相应的默认名称。因此,用户不应该能够对第一项进行输入 - 因此我想禁用第一项的文本框。

我知道我可以在包含类或视图模型的构造函数中运行一个函数,它会禁用第一个索引上的文本框,但是我想知道这是否可以直接在 xaml 代码中(我会找到做这种静态事情的更优雅的方式)。

【问题讨论】:

  • 你看过这个stackoverflow问题吗? stackoverflow.com/questions/20889963/…
  • @KevinCook 据我了解,这个问题的答案再次使用数据绑定来处理视图模型中的 IsEnabled 值,对吗?我想知道有一种仅限 xaml 的方法,我可以根据它们的索引禁用项目。
  • 您必须将 CompositeColelction 指定为 xaml 中的 itemsSource,然后添加 ComboBoxItem 并将 IsHitTestVisible 设置为 false。希望这是有道理的?

标签: c# wpf combobox isenabled


【解决方案1】:

您可以利用 PreviousData RelativeSource 将为集合的第一个元素返回 null 的事实。知道您可以将 DataTrigger 添加到 DataTemplate 以将 TextBoxIsEnabled 属性设置为 false。

这是ItemTemplate 的简化版本,带有PreviousData 绑定:

       <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBox x:Name="TextBox" />
                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=PreviousData}}"
                                 Value="{x:Null}">
                        <Setter TargetName="TextBox" Property="IsEnabled" Value="False" />
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ComboBox.ItemTemplate>

【讨论】:

  • 刚刚测试了这种方法,到目前为止它运行良好。我能想到的唯一一件事是,如果在第一个索引处插入一个新项目,我们会得到两个禁用的项目。任何人,正如上面与 XAMIMAX 讨论的那样,数据触发器是可行的方法 - 将其标记为答案。
【解决方案2】:

我用DataBindingListView 创建了一个复合集合,但逻辑是一样的:

<ListView SelectedValue="{Binding youVMPropertyHere}">
    <ListView.ItemsSource>
        <CompositeCollection>
            <ListViewItem IsHitTestVisible="False">Default Item</ListViewItem>
            <CollectionContainer Collection="{Binding Source={StaticResource cvsPresetLists}}"/>
        </CompositeCollection>
    </ListView.ItemsSource>
<!-- Where-->
<Window.Resources>
    <CollectionViewSource Source="{Binding Presets.VolumePresetList}" x:Key="cvsPresetLists"/>
</Window.Resources>  

这样你可以让第一个项目不可选。我也会使用SelectedValue 而不是SelectedIndex

【讨论】:

  • 嗯,所以如果我理解正确,您示例中的默认项根本不会绑定到 ViewModel 中的PresetList,对吗?
  • 是的,它是一个完全独立的对象。
  • 好的,这通常是有道理的,但不适用于我的情况,因为源列表的每个项目都是一个类对象,包含多个属性(用作不同用户控件的数据上下文)预设名称只是这个类的一个属性。我希望这很有意义;)无论如何我都会将您的回复标记为答案,因为它最接近我想要实现的目标 - 谢谢!
  • 是不是因为你的收藏有默认值?你也可以使用模板选择器,并抛出一个read only 控件,如果这有意义的话?
  • (1/2) 我的组合框的来源是ObservableCollection&lt;PresetModel&gt;。 Presetname 是PresetModel 类的一个属性。如果用户选择了组合框的一项,则显示对应的PresetModel的数据,并且可以由用户更改。如果是第一项(默认项),我想阻止用户更改预设名称。因此,只有当项目的索引为 0 时,我才希望禁用数据模板中的文本框。目前,我只需将Textbox.IsEnabled 标记绑定到 ViewModel 并将其设置在那里即可处理此问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-27
  • 2018-04-15
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 2011-07-27
相关资源
最近更新 更多