Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF ListView SelectedItems数据绑定MVVM_C#_Wpf_Mvvm_Data Binding - Fatal编程技术网

C# WPF ListView SelectedItems数据绑定MVVM

C# WPF ListView SelectedItems数据绑定MVVM,c#,wpf,mvvm,data-binding,C#,Wpf,Mvvm,Data Binding,以下是我认为的源代码 <ListView SelectionMode="Multiple" ItemsSource="{Binding Items, Mode=OneWay}" SelectedItems="{Binding SelectedItems}"> <ListView.ItemTemplate> <DataTemplate> <Grid Height="

以下是我认为的源代码

<ListView SelectionMode="Multiple"
    ItemsSource="{Binding Items, Mode=OneWay}"
    SelectedItems="{Binding SelectedItems}">
        <ListView.ItemTemplate>
             <DataTemplate>
                 <Grid Height="55" Margin="-3,0,-3,0">
                     <TextBlock Text="{Binding Name}"/>
                 </Grid>
             </DataTemplate>
        </ListView.ItemTemplate>
</ListView>
我需要在
SelectedItems属性(ViewModel)
中执行一些操作。
我怎么去那里

我们用一个附加属性解决了它,该属性如下所示:

public class MultiSelectorExtension
{
    public static readonly DependencyProperty SelectedItemsProperty =
        DependencyProperty.RegisterAttached("SelectedItems", typeof(INotifyCollectionChanged), typeof(MultiSelectorExtension),
        new PropertyMetadata(default(INotifyCollectionChanged), OnSelectedItemsChanged));

    public static void SetSelectedItems(DependencyObject element, INotifyCollectionChanged value)
    {
        element.SetValue(SelectedItemsProperty, value);
    }

    public static INotifyCollectionChanged GetSelectedItems(DependencyObject element)
    {
        return (INotifyCollectionChanged)element.GetValue(SelectedItemsProperty);
    }

    private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MultiSelector multiSelectorControl = d as MultiSelector;

        NotifyCollectionChangedEventHandler handler = (sender,
            args) =>
        {
            if (multiSelectorControl != null)
            {
                IList listSelectedItems = multiSelectorControl.SelectedItems;
                if (args.OldItems != null)
                {
                    foreach (var item in args.OldItems)
                    {
                        if (listSelectedItems.Contains(item))
                        {
                            listSelectedItems.Remove(item);
                        }
                    }
                }

                if (args.NewItems != null)
                {
                    foreach (var item in args.NewItems)
                    {
                        if (!listSelectedItems.Contains(item))
                        {
                            listSelectedItems.Add(item);
                        }
                    }
                }
            }
        };

        if (e.OldValue == null && multiSelectorControl != null)
        {
            multiSelectorControl.SelectionChanged += OnSelectionChanged;
        }

        if (e.OldValue is INotifyCollectionChanged)
        {
            (e.OldValue as INotifyCollectionChanged).CollectionChanged -= handler;
        }

        if (e.NewValue is INotifyCollectionChanged)
        {
            (e.NewValue as INotifyCollectionChanged).CollectionChanged += handler;
        }

    }

    private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        DependencyObject d = sender as DependencyObject;

        if (GetSelectionChangedInProgress(d))
            return;

        // Internal Flag to avoid infinite loop 
        SetSelectionChangedInProgress(d, true);

        dynamic selectedItems = GetSelectedItems(d);

        try
        {
            foreach (var item in e.RemovedItems.Cast<dynamic>().Where(item => selectedItems.Contains(item)))
            {
                selectedItems.Remove(item);
            }
        }
        catch (Exception)
        {

        }

        try
        {
            foreach (var item in e.AddedItems.Cast<dynamic>().Where(item => !selectedItems.Contains(item)))
            {
                selectedItems.Add(item);
            }
        }
        catch (Exception)
        {
        }


        SetSelectionChangedInProgress(d, false);
    }


    private static readonly DependencyProperty SelectionChangedInProgressProperty =
        DependencyProperty.RegisterAttached("SelectionChangedInProgress", typeof(bool), typeof(MultiSelectorExtension), new PropertyMetadata(default(bool)));

    private static void SetSelectionChangedInProgress(DependencyObject element,
        bool value)
    {
        element.SetValue(SelectionChangedInProgressProperty, value);
    }

    private static bool GetSelectionChangedInProgress(DependencyObject element)
    {
        return (bool)element.GetValue(SelectionChangedInProgressProperty);
    }
}
AttachedProperties:MultiSelectorExtension.SelectedItems="{Binding SelectedPersonss, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

我们用一个附加属性解决了它,该属性如下所示:

public class MultiSelectorExtension
{
    public static readonly DependencyProperty SelectedItemsProperty =
        DependencyProperty.RegisterAttached("SelectedItems", typeof(INotifyCollectionChanged), typeof(MultiSelectorExtension),
        new PropertyMetadata(default(INotifyCollectionChanged), OnSelectedItemsChanged));

    public static void SetSelectedItems(DependencyObject element, INotifyCollectionChanged value)
    {
        element.SetValue(SelectedItemsProperty, value);
    }

    public static INotifyCollectionChanged GetSelectedItems(DependencyObject element)
    {
        return (INotifyCollectionChanged)element.GetValue(SelectedItemsProperty);
    }

    private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MultiSelector multiSelectorControl = d as MultiSelector;

        NotifyCollectionChangedEventHandler handler = (sender,
            args) =>
        {
            if (multiSelectorControl != null)
            {
                IList listSelectedItems = multiSelectorControl.SelectedItems;
                if (args.OldItems != null)
                {
                    foreach (var item in args.OldItems)
                    {
                        if (listSelectedItems.Contains(item))
                        {
                            listSelectedItems.Remove(item);
                        }
                    }
                }

                if (args.NewItems != null)
                {
                    foreach (var item in args.NewItems)
                    {
                        if (!listSelectedItems.Contains(item))
                        {
                            listSelectedItems.Add(item);
                        }
                    }
                }
            }
        };

        if (e.OldValue == null && multiSelectorControl != null)
        {
            multiSelectorControl.SelectionChanged += OnSelectionChanged;
        }

        if (e.OldValue is INotifyCollectionChanged)
        {
            (e.OldValue as INotifyCollectionChanged).CollectionChanged -= handler;
        }

        if (e.NewValue is INotifyCollectionChanged)
        {
            (e.NewValue as INotifyCollectionChanged).CollectionChanged += handler;
        }

    }

    private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        DependencyObject d = sender as DependencyObject;

        if (GetSelectionChangedInProgress(d))
            return;

        // Internal Flag to avoid infinite loop 
        SetSelectionChangedInProgress(d, true);

        dynamic selectedItems = GetSelectedItems(d);

        try
        {
            foreach (var item in e.RemovedItems.Cast<dynamic>().Where(item => selectedItems.Contains(item)))
            {
                selectedItems.Remove(item);
            }
        }
        catch (Exception)
        {

        }

        try
        {
            foreach (var item in e.AddedItems.Cast<dynamic>().Where(item => !selectedItems.Contains(item)))
            {
                selectedItems.Add(item);
            }
        }
        catch (Exception)
        {
        }


        SetSelectionChangedInProgress(d, false);
    }


    private static readonly DependencyProperty SelectionChangedInProgressProperty =
        DependencyProperty.RegisterAttached("SelectionChangedInProgress", typeof(bool), typeof(MultiSelectorExtension), new PropertyMetadata(default(bool)));

    private static void SetSelectionChangedInProgress(DependencyObject element,
        bool value)
    {
        element.SetValue(SelectionChangedInProgressProperty, value);
    }

    private static bool GetSelectionChangedInProgress(DependencyObject element)
    {
        return (bool)element.GetValue(SelectionChangedInProgressProperty);
    }
}
AttachedProperties:MultiSelectorExtension.SelectedItems="{Binding SelectedPersonss, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

这并不重要,因为我发布的源代码不是完整的(不是真实的)。实际上,SelectedItems不仅仅是字符串的一个可观察集合,而是某些对象的集合。我需要得到那些东西。即使在setter中设置断点,也不能停止程序。哦,我明白了。那么你的问题是绑定似乎不起作用了?你的问题并不完全清楚。我假设您已经实现了INotifyPropertyChanged(看起来是这样的)?啊,看来SelectedItems是一种方式-您不能从XAML内部设置它。Tomtom的答案应该对您有所帮助。这并不重要,因为我发布的源代码并不完整(不是真正的源代码)。实际上,SelectedItems不仅仅是字符串的一个可观察集合,而是某些对象的集合。我需要得到那些东西。即使在setter中设置断点,也不能停止程序。哦,我明白了。那么你的问题是绑定似乎不起作用了?你的问题并不完全清楚。我假设您已经实现了INotifyPropertyChanged(看起来是这样的)?啊,看来SelectedItems是一种方式-您不能从XAML内部设置它。Tomtom的回答应该对你有帮助。谢谢你——这很有效!如果调试程序,我会看到SelectedItems属性包含ListView中的所有选定项。如果用户选择或取消选择项目,是否有方法引发事件。我需要在ViewModel中处理ListView选择的更改。正如我提到的,如果在我的setter中设置了一个断点,程序就不会停在那里。如果这个答案是您的解决方案的答案,请将其标记为已接受。对于其他疑问和疑问,请问另一个问题!!谢谢你,这很有效!如果调试程序,我会看到SelectedItems属性包含ListView中的所有选定项。如果用户选择或取消选择项目,是否有方法引发事件。我需要在ViewModel中处理ListView选择的更改。正如我提到的,如果在我的setter中设置了一个断点,程序就不会停在那里。如果这个答案是您的解决方案的答案,请将其标记为已接受。对于其他疑问和疑问,请问另一个问题!!