xamlwinui-3winuiwindows-community-toolkit

Only set selectedItem binding in a twoway scenario if one item is selected


In a datagrid context where there is a two way binding on the selected item, how do you prevent the g.cs code from updating the binding if multiple rows are selected?

  <dataGridControl:DataGrid 
         SelectedItem="{x:Bind Model.SelectedItem, Mode=TwoWay}"

In a scenario where the user selects multiple rows, it uses the last selected row when when you select multiple, and of course, considering it is a two way binding, you can not clear the selected item property in the view model without clearing the entire DataGrid selection. The selected item in the view model is misleading considering multiple rows are selected, and not the last one.


Solution

  • The SelectedItem is set internally and is hard to change its behavior.

    Instead, you can create a custom DataGrid control and override the SelectedItems property with an ObservableCollection.

    public class DataGridEx : DataGrid
    {
        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register(
                nameof(SelectedItems),
                typeof(IList),
                typeof(DataGridEx),
                new PropertyMetadata(new ObservableCollection<object>()));
    
        public DataGridEx() : base()
        {
            this.SelectionChanged += (s, e) =>
            {
                foreach (object item in e.RemovedItems)
                {
                    SelectedItems.Remove(item);
                }
    
                foreach (object item in e.AddedItems)
                {
                    SelectedItems.Add(item);
                }
            }
        }
    
        public new IList SelectedItems
        {
            get => (IList)GetValue(SelectedItemsProperty);
            set => SetValue(SelectedItemsProperty, value);
        }
    }
    

    UPDATE

    From the comments:

    What if I only want to update the selected item in the model if one row is selected, instead of using a collection?

    It's hard to change the SelectedItem behavior. I guess you can try creating a value converter. For example:

    public class GreaterThanOneToNullConverter : IValueConverter
    {
        public object? Convert(object value, Type targetType, object parameter, string language)
        {
            return value is IList list && list.Count > 0
                ? list[0]
                : null;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }