Catel and setting usercontrol's DataContext

363 Views Asked by At

I've tried to find a solution myself but I was not able, for some reason the DataContext is not correctly set up in the usercontrol's viewmodel

The idea is to have a single usercontrol that permits to perform a query on a fixed collection and allows the user to drop a treeviewitem that holds an item of the collection (in case the user have the treeview open)

In my main view I've defined :

<views:PortfolioChooserView x:Name="PortfolioChooserView" DataContext="{Binding PortfolioCompleteBox}" Height="25" LoadDefaultValue="True"  />

Where PortfolioCompleteBox is a ViewModel defined in the MainViewModel as

    public PortfolioChooserViewModel PortfolioCompleteBox
    {
        get { return GetValue<PortfolioChooserViewModel>(PortfolioChooserViewModelProperty); }
        set { SetValue(PortfolioChooserViewModelProperty, value); }
    }

    public static readonly PropertyData PortfolioChooserViewModelProperty = RegisterProperty("PortfolioCompleteBox", typeof(PortfolioChooserViewModel));

    public MainViewModel(ICreditLimitRepository creditLimitRepository, IDynamicContainer dynamicContainer)
    {
        this.creditLimitRepository = creditLimitRepository;
        this.dynamicContainer = dynamicContainer;

        LoadCreditLimitsCommand = new Command<object>(OnLoadCreditLimitsExecute, (() => OnLoadCreditLimitsCanExecute));

        var viewModelFactory = this.GetServiceLocator().ResolveType<IViewModelFactory>();

        PortfolioCompleteBox = viewModelFactory.CreateViewModel<PortfolioChooserViewModel>(null);
        Model = new FiltersLoadModel();
    }

My problem is that on the PortFolioChooserView I've the DataContext set to null (and I got 2 calls to the PortFolioChooserViewModel, one from the MainViewModel and the other one from the PortFolioChooserView's viewmodel locator)

public partial class PortfolioChooserView
{
    private PortfolioChooserViewModel viewModel;
    readonly bool isFirstLoad = true;

    /// <summary>
    /// Initializes a new instance of the <see cref="PortfolioChooserView"/> class.
    /// </summary>
    /// 
    public PortfolioChooserView()
    {
        InitializeComponent();

        if (isFirstLoad)
        {
            PortfolioCompleteBox.AllowDrop = true;

            DragDropManager.AddPreviewDragOverHandler(PortfolioCompleteBox, OnElementDragOver);
            DragDropManager.AddDropHandler(PortfolioCompleteBox, OnElementDrop);

            isFirstLoad = false;

            this.Loaded += PortfolioChooserView_Loaded;
            this.DataContextChanged += PortfolioChooserView_DataContextChanged;
        }
    }

    void PortfolioChooserView_DataContextChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
    {
        int t = 0;
    }

    void PortfolioChooserView_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        viewModel = (PortfolioChooserViewModel)this.DataContext;
    }

    private void OnElementDragOver(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
    {
        var options = Telerik.Windows.DragDrop.DragDropPayloadManager.GetDataFromObject(e.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;

        if (options != null)
        {
            var visual = options.DragVisual as TreeViewDragVisual;

            if (visual != null) visual.IsDropPossible = true;
        }

        e.Handled = true;
    }

    private void OnElementDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
    {
        var context = ((IPortfolioAutoComplete)this.DataContext);

        context.SetPortfolioAutoCompleteBox(e);
    }

    public static readonly DependencyProperty LoadDefaultValueProperty = DependencyProperty.Register(
  "LoadDefaultValue", typeof(bool), typeof(PortfolioChooserView), new PropertyMetadata(default(bool)));



    public bool LoadDefaultValue
    {
        get { return (bool)GetValue(LoadDefaultValueProperty); }
        set { SetValue(LoadDefaultValueProperty, value); }
    }

}

What am I doing wrong? Thanks

1

There are 1 best solutions below

0
On
  1. Don't try to manage your own vm's
  2. Catel will automatically accept a parent-vm as it's own vm as long as they are compatible. You don't need to handle this manually in your view loading in the view.
  3. Instead of creating a VM in the parent VM, use a model only (so the vm only cares about what the VM itself should do). Then set the DC of the PortfolioChooserView to the model. Then the vm of the child view can accept the model in the ctor and be managed on it's own.

There are much better ways to communicate between vm's then trying to micro-manage like you are doing now. As always, see the docs.