Home > Enterprise >  How to set ComboBoxItem property?
How to set ComboBoxItem property?

Time:10-16

I am trying to hide an item in the Combobox when it has been selected and this is how my code looks like right now:

VeiwModel.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"));
                }
            }
        }

MainPage.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>

I am not sure how the Binding part works on the Setter property as I think it's not getting the IsSelectable property from the Items class....

CodePudding user response:

Please refer to document here, UWP does not support bindings in Style Setters. It will not effect when you binding ItemContainerStyle style.

Windows Presentation Foundation (WPF) and Microsoft Silverlight supported the ability to use a Binding expression to supply the Value for a Setter in a Style. The Windows Runtime doesn't support a Binding usage for Setter.Value (the Binding won't evaluate and the Setter has no effect, you won't get errors, but you won't get the desired result either). When you convert XAML styles from Windows Presentation Foundation (WPF) or Microsoft Silverlight XAML, replace any Binding expression usages with strings or objects that set values, or refactor the values as shared {StaticResource} markup extension values rather than Binding -obtained values.

For this scenario, A workaround could be a helper class with attached properties for the source paths of the bindings. It will create the binding expression in code behind in a PropertyChangedCallback of the helper property.

I have edited your code and xaml, please refer to the following code the implement.

<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# Code

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"));
            }
        }
    }
}
  • Related