如何使用 MVVM 在 WPF 中设置 GridView 的 SelectedItems 属性

发布于 2024-12-06 05:44:14 字数 3340 浏览 0 评论 0原文

我的 wpf 应用程序中有一个 gridview,其 xaml 如下所示:

   <ListView SelectionMode="Extended" ItemsSource="{Binding AllPartTypes}"
      local:DataGridService.SelectedItems="{Binding Path=SelectedPartTypes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        <ListView.View>
            <GridView>
                some columns...
            </GridView>
        </ListView.View>
   </ListView>

这是我用来获取所选项目的附加行为:

public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached(
            "SelectedItems",
            typeof(IList),
            typeof(DataGridService),
             new UIPropertyMetadata(new List<object>() as IList, OnSelectedItemsChanged));

        static SelectionChangedEventHandler GetSelectionChangedHandler(DependencyObject obj)
        {
            return (SelectionChangedEventHandler)obj.GetValue(SelectionChangedHandlerProperty);
        }
        static void SetSelectionChangedHandler(DependencyObject obj, SelectionChangedEventHandler value)
        {
            obj.SetValue(SelectionChangedHandlerProperty, value);
        }
        static readonly DependencyProperty SelectionChangedHandlerProperty =
            DependencyProperty.RegisterAttached("SelectionChangedHandler", typeof(SelectionChangedEventHandler),
            typeof(DataGridService), new UIPropertyMetadata(null));

        //d is MultiSelector (d as ListBox not supported)
        static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
        {
            if (GetSelectionChangedHandler(d) != null)
                return;

            if (d is MultiSelector)//DataGrid
            {
                MultiSelector multiselector = d as MultiSelector;
                SelectionChangedEventHandler selectionchanged = null;
                foreach (var selected in (d as DataGrid).SelectedItems) // GetSelectedItems(d) as IList)
                    multiselector.SelectedItems.Add(selected);

                selectionchanged = (sender, e) =>
                {
                    SetSelectedItems(d, multiselector.SelectedItems);
                };
                SetSelectionChangedHandler(d, selectionchanged);
                multiselector.SelectionChanged += GetSelectionChangedHandler(d);
            }
            else if (d is ListBox)
            {
                ListBox listbox = d as ListBox;
                SelectionChangedEventHandler selectionchanged = null;

                selectionchanged = (sender, e) =>
                {
                    SetSelectedItems(d, listbox.SelectedItems);
                };
                SetSelectionChangedHandler(d, selectionchanged);
                listbox.SelectionChanged += GetSelectionChangedHandler(d);
            }
        }

        public static IList GetSelectedItems(DependencyObject obj)
        {
            return (IList)obj.GetValue(SelectedItemsProperty);
        }

        public static void SetSelectedItems(DependencyObject obj, IList value)
        {
            obj.SetValue(SelectedItemsProperty, value);
        }

当用户单击 a 时,这对于在视图模型中获取所选项目效果很好。按钮什么的。我的问题是,当屏幕加载时,我需要突出显示之前选择的项目。我尝试在虚拟机的构造函数中设置“SelectedPartTypes”属性,但没有成功,假设双向绑定会处理它。有没有一种简单的方法来显示控件加载时选择了哪些项目?

I've got a gridview in my wpf application, the xaml of which looks like this:

   <ListView SelectionMode="Extended" ItemsSource="{Binding AllPartTypes}"
      local:DataGridService.SelectedItems="{Binding Path=SelectedPartTypes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        <ListView.View>
            <GridView>
                some columns...
            </GridView>
        </ListView.View>
   </ListView>

Here is the attached behavior I'm using to get the selected items:

public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached(
            "SelectedItems",
            typeof(IList),
            typeof(DataGridService),
             new UIPropertyMetadata(new List<object>() as IList, OnSelectedItemsChanged));

        static SelectionChangedEventHandler GetSelectionChangedHandler(DependencyObject obj)
        {
            return (SelectionChangedEventHandler)obj.GetValue(SelectionChangedHandlerProperty);
        }
        static void SetSelectionChangedHandler(DependencyObject obj, SelectionChangedEventHandler value)
        {
            obj.SetValue(SelectionChangedHandlerProperty, value);
        }
        static readonly DependencyProperty SelectionChangedHandlerProperty =
            DependencyProperty.RegisterAttached("SelectionChangedHandler", typeof(SelectionChangedEventHandler),
            typeof(DataGridService), new UIPropertyMetadata(null));

        //d is MultiSelector (d as ListBox not supported)
        static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
        {
            if (GetSelectionChangedHandler(d) != null)
                return;

            if (d is MultiSelector)//DataGrid
            {
                MultiSelector multiselector = d as MultiSelector;
                SelectionChangedEventHandler selectionchanged = null;
                foreach (var selected in (d as DataGrid).SelectedItems) // GetSelectedItems(d) as IList)
                    multiselector.SelectedItems.Add(selected);

                selectionchanged = (sender, e) =>
                {
                    SetSelectedItems(d, multiselector.SelectedItems);
                };
                SetSelectionChangedHandler(d, selectionchanged);
                multiselector.SelectionChanged += GetSelectionChangedHandler(d);
            }
            else if (d is ListBox)
            {
                ListBox listbox = d as ListBox;
                SelectionChangedEventHandler selectionchanged = null;

                selectionchanged = (sender, e) =>
                {
                    SetSelectedItems(d, listbox.SelectedItems);
                };
                SetSelectionChangedHandler(d, selectionchanged);
                listbox.SelectionChanged += GetSelectionChangedHandler(d);
            }
        }

        public static IList GetSelectedItems(DependencyObject obj)
        {
            return (IList)obj.GetValue(SelectedItemsProperty);
        }

        public static void SetSelectedItems(DependencyObject obj, IList value)
        {
            obj.SetValue(SelectedItemsProperty, value);
        }

This works fine for getting the selected items in the viewmodel when the user clicks a button or something. My problem is that, when the screen loads, I need to highlight the items which were previously selected. I unsuccessfully tried setting the 'SelectedPartTypes' property in the constructor of the VM, assuming that the two-way binding would take care of it. Is there an easy way to show which items are selected when the control loads?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北城挽邺 2024-12-13 05:44:14

不能在 ListBoxItem 样式中绑定 IsSelected 属性吗?

<Style TargetType="ListBoxItem">
    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>

如果您的数据对象没有用于跟踪选择的属性,并且当前对象位于 SelectedPartTypes 内,则您可能需要使用转换器返回 true

Can't you bind the IsSelected property in the ListBoxItem Style?

<Style TargetType="ListBoxItem">
    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>

If your data objects don't have a property to track selection, you may need to use a converter to return true if the current object is within SelectedPartTypes

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文