1
votes

Searched a lot on the site and read a lot of similar questions, but nothing seems to resolve what I'm not understanding with my User Control.

I have a user control implemented with MVVM. Basically is a grid of folders where every folder is a checkbox and a path. User can selecth any folder checking the checkbox. User Control xaml is:

<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 is:

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 is:

    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");}
    }
    [...]
}

I then use a WPF application where I put my user control. If I bind the user control DP SelectedFolders with ItemSource, all is working right. If I check the folder checkbox of the user control the SelectedFolder are update on the item source.

<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 is:

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");}
    }
}

I do not have any message in the output window about binding so all the binding path should be ok. I think the binding between window view model and DP of the control is borken by the binding between the User Control and the User Control view model. But I don't know why and how to solve the problem. I tried to change the DataContex of the user control in many ways but the result is always the same. Anyone could lead me in the right direction?

1
Welcome to Stack Overflow. For future reference, you have displayed far too much code in this question. On this website, you're supposed to create a Minimal, Complete, and Verifiable example and show us that instead. Doing this, will help you and us and will ensure that you get answers quickly - note that with this overload of code, you have still not received a single answer yet.Sheridan
@puckk sheridan is right...your code seems to jumbled up... in your usercontrol datagrid itemssource is bound to Folders while your DP name is SelectedFolders.. why do you need to call setbinding in the usercontrol constructor?Nitin
Cleaned the code a bit... hope is better now :).puckkk
@nit Datagrid Itemsource is bound to Folders of the user control viewmodel. When the collection change SelectedFoldersV is set. SetBinding on the constructor bind the DP (SelectedFoldersProperty) to SelectedfoldersV propriety of the user control viewmodel.puckkk

1 Answers

1
votes

In the first example you have SelectedFolders DependencyProperty of the ViewCTRL bound to SelectedFoldersV of the ViewCTRLModel. The ItemsSource of the ListBox is then bound to the SelectedFolders DependencyProperty.

In the second example you have SelectedFolders DependencyProperty of the ViewCTRL bound to SelectedFoldersVMWPF property of ViewWPFModel (during the InitializeComponent() call in the ViewCTRL constructor). But then immediately following this the Binding is changed to SelectedFoldersV of the ViewCTRLModel by your SetBindings call.

I haven't done this before but I think this should work if you change SelectedFoldersV to a DependencyProperty in your ViewModel and make the following change to your ViewCTRL constructor:

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

Please note there probably is better ways of achieving what you are attempting to do (such as using MVVM Light's Messenger to communicate these kinds of changes between ViewModels). I personally wouldn't want to chain a bunch of bindings together as I think that is more confusing.