首页 > 解决方案 > 如何设置 ComboBoxItem 属性?

问题描述

我试图在组合框中隐藏一个项目,当它被选中时,这就是我的代码现在的样子:

视图模型.cs

        public class SortList
        {
            public string Key { get; set; }
            public string Value { get; set; }
            public bool IsSelectable { get; set; }
        }
        private void InitSortList()
        {
            ObservableCollection<SortList> sl = new ObservableCollection<SortList>();

            foreach(var i in defaultSortList)
            {
                SortList s = new SortList();
                s.Key = i.Key.ToString();
                s.Value = i.Value.ToString();
                s.IsSelectable = false;
                sl.Add(s);
            }

            _items = sl;
        }

        private ObservableCollection<SortList> _items = new ObservableCollection<SortList>();
        public ObservableCollection<SortList> Items
        {
            get { 
                return _items; }
        }


        private SortList _selectedSort;
        public SortList SelectedItem
        {
            get { return _selectedSort; }
            set
            {
                if(_selectedSort != value)
                {
                    _selectedSort = value;
                    _selectedSort.IsSelectable = false;
                    PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
                }
            }
        }

主页.xaml

 <ComboBox Header="Sort 1" HorizontalAlignment="Stretch"
                                                  Name="Sort_1" SelectionChanged="comboSelectionChanged"
                                                  ItemsSource="{Binding Items, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                 SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                                                  SelectedValuePath="Key"
                                            DisplayMemberPath="Value" 
                                                  >
                                            <ComboBox.ItemContainerStyle>
                                                <Style TargetType="ComboBoxItem" BasedOn="ComboBoxIem">
                                                    <Setter
                                                         Property="IsEnabled"
                                                         Value="{Binding Items.IsSelectable, Mode=TwoWay}" />

//Binding IsSelectable doesnt work either
                                                   
                                                </Style>
                                            </ComboBox.ItemContainerStyle>
                                        </ComboBox>

我不确定 Binding 部分如何在 Setter 属性上工作,因为我认为它没有从 Items 类中获取 IsSelectable 属性......

标签: c#xamlwindows-runtimewinrt-xamlwinui-3

解决方案


请参阅此处的文档,UWP 不支持样式设置器中的绑定。ItemContainerStyle绑定样式时不会影响。

Windows Presentation Foundation (WPF) 和 Microsoft Silverlight 支持使用绑定表达式为样式中的 Setter 提供值的能力。Windows 运行时不支持 Setter.Value 的 Binding 用法(Binding 不会计算并且 Setter 没有效果,您不会收到错误,但也不会获得所需的结果)。从 Windows Presentation Foundation (WPF) 或 Microsoft Silverlight XAML 转换 XAML 样式时,请将任何 Binding 表达式用法替换为设置值的字符串或对象,或将值重构为共享 {StaticResource} 标记扩展值而不是 Binding 获得的值。

对于这种情况,一种解决方法可能是一个辅助类,它带有绑定源路径的附加属性。它将在PropertyChangedCallback辅助属性的 a 后面的代码中创建绑定表达式。

我已经编辑了你的代码和xaml,请参考下面的代码实现。

<Page.DataContext>
    <local:ViewModel />
</Page.DataContext>
<Grid>
    <ComboBox
        Name="Sort_1"
        HorizontalAlignment="Stretch"
        DisplayMemberPath="Value"
        Header="Sort 1"
        ItemsSource="{Binding Items, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
        SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
        SelectedValuePath="Key"
        SelectionChanged="comboSelectionChanged">
        <ComboBox.ItemContainerStyle>
            <Style TargetType="ComboBoxItem">
                <Setter Property="local:BindingHelper.IsEnable" Value="IsSelectable" />
            </Style>
        </ComboBox.ItemContainerStyle>
    </ComboBox>
</Grid>

C# 代码

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

    }

    private void comboSelectionChanged(object sender, SelectionChangedEventArgs e)
    {

    }
}

public class BindingHelper
{
    public static string GetIsEnable(DependencyObject obj)
    {
        return (string)obj.GetValue(IsEnableProperty);
    }
    public static void SetIsEnable(DependencyObject obj, string value)
    {
        obj.SetValue(IsEnableProperty, value);
    }
    // Using a DependencyProperty as the backing store for IsEnable.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsEnableProperty =
        DependencyProperty.RegisterAttached("IsEnable", typeof(string), typeof(BindingHelper), new PropertyMetadata(null, GridBindingPathPropertyChanged));

    private static void GridBindingPathPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var propertyPath = e.NewValue as string;
        if (propertyPath != null)
        {
            var bindingProperty =
                e.Property == IsEnableProperty
                ? ComboBoxItem.IsEnabledProperty
                : null;
            BindingOperations.SetBinding(
                obj,
                bindingProperty,
                new Binding { Path = new PropertyPath(propertyPath) });
        }
    }
}

public class ViewModel : INotifyPropertyChanged
{
    public class SortList : INotifyPropertyChanged
    {
        public string Key { get; set; }
        public string Value { get; set; }
        private bool _isSelectable;
        public bool IsSelectable
        {
            get { return _isSelectable; }
            set
            {
                _isSelectable = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string PropertyName = null)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
    }
    public ViewModel()
    {
        defaultSortList = new Dictionary<string, string>();
        defaultSortList.Add("0", "item");
        defaultSortList.Add("1", "item1");
        defaultSortList.Add("2", "item2");
        defaultSortList.Add("3", "item3");

        InitSortList();
    }
    private Dictionary<string, string> defaultSortList;
    private void InitSortList()
    {
        ObservableCollection<SortList> sl = new ObservableCollection<SortList>();

        foreach (var i in defaultSortList)
        {
            SortList s = new SortList();
            s.Key = i.Key.ToString();
            s.Value = i.Value.ToString();
            s.IsSelectable = true;
            sl.Add(s);
        }

        _items = sl;
    }

    private ObservableCollection<SortList> _items = new ObservableCollection<SortList>();
    public ObservableCollection<SortList> Items
    {
        get
        {
            return _items;
        }
    }

    private SortList _selectedSort;
    public event PropertyChangedEventHandler PropertyChanged;
    public SortList SelectedItem
    {
        get { return _selectedSort; }
        set
        {
            if (_selectedSort != value)
            {
                _selectedSort = value;
                _selectedSort.IsSelectable = false;
                PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
            }
        }
    }
}

推荐阅读