首页 文章

WPF用户控制MVVM

提问于
浏览
1

在网站上搜索了很多并阅读了很多类似的问题,但似乎没有解决我用户控件无法理解的问题 .

我有一个用MVVM实现的用户控件 . 基本上是一个文件夹网格,其中每个文件夹都是一个复选框和一个路径 . 用户可以选中任何检查复选框的文件夹 . User Control xaml 是:

<UserControl x:Class="TestDP.Views.ViewCTRL" [...]>
        <DataGrid Name="GridMain" ItemsSource="{Binding Folders}">
        <DataGrid.Columns>
            <DataGridCheckBoxColumn Header="Cked" Binding="{Binding Cked,  UpdateSourceTrigger=PropertyChanged}" />
            <DataGridTextColumn Header="Path" Binding="{Binding Path}"/>
        </DataGrid.Columns>
    </DataGrid>
</UserControl>

User control code behind 是:

public partial class ViewCTRL : UserControld
{
    public static DependencyProperty SelectedFoldersProperty =
        DependencyProperty.Register("SelectedFolders", typeof(ObservableCollection<Folder>), typeof(ViewCTRL),
        new FrameworkPropertyMetadata() { BindsTwoWayByDefault = true });

    public ObservableCollection<Folder> SelectedFolders
    {
        get{return (ObservableCollection<Folder>)GetValue(SelectedFoldersProperty);}
        set{SetValue(SelectedFoldersProperty, value);}}

    public ViewCTRL()
    {
        var vm = new ViewCTRLModel();
        InitializeComponent();
        GridMain.DataContext = vm;

        // bindings
        SetBinding(SelectedFoldersProperty, new Binding()
        {
            Source = GridMain.DataContext,
            Path = new PropertyPath("SelectedFoldersV"),
            UpdateSourceTrigger =   System.Windows.Data.UpdateSourceTrigger.PropertyChanged,
            Mode = BindingMode.TwoWay
        });
    }

User Control ViewModel 是:

public class ViewCTRLModel : INotifyPropertyChanged
{
    [...]

    public void Folder_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        SelectedFoldersV = new ObservableCollection<Folder>(Folders.Where(x => x.Cked));
    }

    private ObservableCollection<Folder> folders;
    public ObservableCollection<Folder> Folders
    {
        get{return folders;}
        set{folders = value;OnPropertyChanged("Folders");}
    }

    private ObservableCollection<Folder> selectedFoldersV;
    public ObservableCollection<Folder> SelectedFoldersV
    {
        get{return selectedFoldersV;}
        set{selectedFoldersV = value;OnPropertyChanged("SelectedFoldersV");}
    }
    [...]
}

然后我使用WPF应用程序,我放置了我的用户控件 . 如果我将用户控件DP SelectedFolders绑定到 ItemSource ,则一切正常 . 如果我检查用户控件的文件夹复选框,则选择项目源上的SelectedFolder .

<Window x:Class="TestDPWPF.Views.ViewWPF" [...]>
<uc:ViewCTRL Name="ViewCTRL" />
<ListBox ItemsSource="{Binding ElementName=ViewCTRL, Path=SelectedFolders}" DisplayMemberPath="Path"/>

If I Bind the SelectedFolders Propery to a Property of the Window view model like

<uc:ViewCTRL Name="ViewCTRL" SelectedFolders="{Binding SelectedFoldersVMWPF,  Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

the usercontrol get the initial values passed by the window viewmodel but then binding seems broken and selecting any folder does not update the SelectedFoldersVMWPF binding.

Viewmodel of the windows 是:

class ViewWPFModel : INotifyPropertyChanged
{
    public ViewWPFModel()
    {
        SelectedFoldersVMWPF = new ObservableCollection<Folder>();
        SelectedFoldersVMWPF.Add(new Folder() { Path = "uuu" });
    }

    private ObservableCollection<Folder> selectedFoldersVMWPF;
    public ObservableCollection<Folder> SelectedFoldersVMWPF
    {
        get {return selectedFoldersVMWPF;}
        set {selectedFoldersVMWPF = value; OnPropertyChanged("SelectedFoldersVMWPF");}
    }
}

我在输出窗口中没有关于绑定的任何消息,因此所有绑定路径都应该没问题 . 我认为窗口视图模型和控件的DP之间的绑定是由用户控件和用户控件视图模型之间的绑定决定的 . 但我不知道为什么以及如何解决这个问题 . 我尝试以多种方式更改用户控件的DataContex,但结果始终相同 . 任何人都可以带领我朝着正确的方向前进

1 回答

  • 1

    在第一个示例中,ViewCTRL的SelectedFolders DependencyProperty绑定到ViewCTRLModel的SelectedFoldersV . 然后将ListBox的ItemsSource绑定到SelectedFolders DependencyProperty .

    在第二个示例中,ViewCTRL的SelectedFolders DependencyProperty绑定到ViewWPFModel的SelectedFoldersVMWPF属性(在ViewCTRL构造函数的InitializeComponent()调用期间) . 但随后紧接着,通过SetBindings调用将Binding更改为ViewCTRLModel的SelectedFoldersV .

    我之前没有这样做过,但我认为如果你在ViewModel中将SelectedFoldersV更改为DependencyProperty并对ViewCTRL构造函数进行以下更改,这应该可行:

    SetBinding(vm.SelectedFoldersVProperty, new Binding()
        {
            Source = this,
            Path = new PropertyPath("SelectedFolders"),
            UpdateSourceTrigger = System.Windows.Data.UpdateSourceTrigger.PropertyChanged,
            Mode = BindingMode.TwoWay
        });
    

    请注意,可能有更好的方法来实现您尝试执行的操作(例如使用MVVM Light的Messenger在ViewModel之间传递这些类型的更改) . 我个人不希望将一堆绑定链接在一起,因为我认为这更令人困惑 .

相关问题