简体   繁体   English

如何将 ItemsControl 成员的 ICommand 的依赖属性绑定到父视图 model?

[英]How to bind dependency property of ICommand of ItemsControl member to parent view model?

I have a custom user control that has a checkbox and a button with backing dependency properties.我有一个自定义用户控件,它有一个复选框和一个带有支持依赖属性的按钮。

I also have a window with an ItemsControl and I bind that control's "ItemsSource" to an ObservableCollection containing said user controls.我还有一个带有 ItemsControl 的 window 并将该控件的“ItemsSource”绑定到包含所述用户控件的 ObservableCollection。

My goal is to be able to access the dependency properties in the window's view model, so I can check whether the checkbox of each member of the collection is checked or not and when the user clicks the button - remove the user control containing the button from the collection.我的目标是能够访问窗口视图 model 中的依赖项属性,因此我可以检查集合中每个成员的复选框是否被选中以及当用户单击按钮时 - 删除包含该按钮的用户控件集合。

This is my code这是我的代码

User control XAML:用户控制XAML:

<CheckBox IsChecked="{Binding cbChecked,
            Mode=OneWayToSource,
            UpdateSourceTrigger=PropertyChanged,
            RelativeSource={RelativeSource FindAncestor,
            AncestorType=UserControl}}"/>


<Button Content="X"
        Command="{Binding RemoveCommand,
                    RelativeSource={RelativeSource FindAncestor,
                    AncestorType=UserControl}}">

(note I am not sure if I need the "UpdateSourceTrigger") (注意我不确定是否需要“UpdateSourceTrigger”)

User control codebehind:用户控制代码隐藏:

    public ICommand RemoveCommand
    {
        get { return (ICommand)GetValue(RemoveCommandProperty); }
        set { SetValue(RemoveCommandProperty, value); }
    }

    // Using a DependencyProperty as the backing store for RemoveCommand.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty RemoveCommandProperty =
        DependencyProperty.Register("RemoveCommand", typeof(ICommand), typeof(CustomUserControl), new PropertyMetadata(OnAnyPropertyChanged));

    public bool cbChecked
    {
        get { return (bool)GetValue(cbCheckedProperty); }
        set { SetValue(cbCheckedProperty, value); }
    }

    // Using a DependencyProperty as the backing store for cbChecked.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty cbCheckedProperty =
        DependencyProperty.Register("cbChecked", typeof(bool), typeof(CustomUserControl), new PropertyMetadata(OnAnyPropertyChanged));

    static void OnAnyPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        => (obj as CustomUserControl).OnAnyPropertyChanged(args);

    void OnAnyPropertyChanged(DependencyPropertyChangedEventArgs args)
        => AnyPropertyChanged?.Invoke(this, args);

Window XAML: Window XAML:

        <ScrollViewer VerticalScrollBarVisibility="Visible" Grid.Row="0">
            <ItemsControl ItemsSource="{Binding ControlsCollection}" HorizontalAlignment="Stretch" VerticalAlignment="Top">
                <ItemsControl.ItemContainerStyle>
                    <Style>
                        <Setter Property="FrameworkElement.Margin" Value="5,20,0,0"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
        </ScrollViewer>

How can I make it so when the user clicks the "X" button the user control that holds it is removed from the collection AND be able to check the checkbox "checked" status from the window's view model?我怎样才能做到这一点,当用户单击“X”按钮时,持有它的用户控件将从集合中删除,并且能够从窗口视图 model 中选中复选框“已检查”状态?

First, you should not hold an element of view in view model.首先,您不应在视图 model 中持有视图元素。 The item of ObservableCollection should be item's view model rather than UserControl. ObservableCollection 的项目应该是项目的视图 model 而不是 UserControl。

Second, you don't need to use a UserControl in such case.其次,在这种情况下,您不需要使用 UserControl。 A DataTemplate which has the same elements will suffice.具有相同元素的 DataTemplate 就足够了。

For example, a minimal item's view model would be as follows.例如,最小项目的视图 model 将如下所示。

using CommunityToolkit.Mvvm.ComponentModel;

public partial class ItemViewModel : ObservableObject
{
    [ObservableProperty]
    public bool _checked;
}

Then, window's view model.然后,窗口视图 model。

using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

public class MainWindowViewModel : ObservableObject
{
    public ObservableCollection<ItemViewModel> ItemsCollection { get; } = new();

    public MainWindowViewModel()
    {
        ItemsCollection.Add(new ItemViewModel());
        ItemsCollection.Add(new ItemViewModel());
        ItemsCollection.Add(new ItemViewModel());
    }

    public ICommand RemoveCommand => _removeCommand ??= new RelayCommand<ItemViewModel>(item => Remove(item));
    private RelayCommand<ItemViewModel>? _removeCommand;

    private void Remove(ItemViewModel? item)
    {
        if (item is not null)
        {
            Debug.WriteLine($"Checked:{item.Checked}");

            ItemsCollection.Remove(item);
        }
    }
}

The window's view.窗户的景色。 The elements of DataTemplate of ItemsControl.ItemTemplate are the same as your UserControl but bindings are modified. ItemsControl.ItemTemplate 的 DataTemplate 的元素与您的 UserControl 相同,但修改了绑定。

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp"
        Title="MainWindow"
        Width="600" Height="300">
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>

    <ScrollViewer VerticalScrollBarVisibility="Visible">
        <ItemsControl ItemsSource="{Binding ItemsCollection}"
                      HorizontalAlignment="Stretch" VerticalAlignment="Top">
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="FrameworkElement.Margin" Value="5,20,0,0"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <CheckBox IsChecked="{Binding Checked, Mode=OneWayToSource}"/>
                        <Button Content="X"
                                Command="{Binding DataContext.RemoveCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
                                CommandParameter="{Binding DataContext, RelativeSource={RelativeSource Self}}"/>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Window>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从父类的ItemsControl绑定子类的属性 - How to bind property of child class from itemscontrol of parent class WPF/MVVM:如何从 ItemsControl 将模型绑定到视图/视图模型 - WPF/MVVM : How to bind model to view/viewmodel from ItemsControl 将ICommand绑定到父ViewModel - Bind ICommand to parent ViewModel ICommand依赖属性 - ICommand Dependency Property 如何使用Style将子UserControl的Dependency属性绑定到宿主元素的视图模型的属性? - How to bind a child `UserControl`'s Dependency Property, using `Style`, to a property of the host element's view-model? 在ItemControl中具有依赖项属性的UserControl:如何将ItemSource的元素绑定到UserControl的x:Name? - UserControl with Dependency Property inside an ItemsControl: how to Bind element of ItemSource to x:Name of UserControl? WPF CustomControl无法绑定依赖项属性的两种方式查看模型 - WPF CustomControl unable to bind dependency property two way to view model 如何绑定Func <T,T,T> 从视图模型到XAML中的依赖属性? - How to bind Func<T,T,T> to dependency property in XAML from view model? 如何在ItemsControl中的用户控件中绑定特定属性 - how to bind specific property in user control in itemscontrol 当 itemSource 绑定到 Model (\ - How could one set the command property of a button in a View to an ICommand in the associated ViewModel when the itemSource is bound to a Model (\
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM