Catel并设置usercontrol的DataContext

时间:2015-06-26 07:46:27

标签: wpf catel

我自己试图找到一个解决方案,但由于某种原因,我无法在usercontrol的viewmodel中正确设置DataContext

我们的想法是拥有一个允许对固定集合执行查询的用户控件,并允许用户删除包含集合项的treeviewitem(如果用户打开了树视图)

在我的主视图中,我已定义:

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

其中PortfolioCompleteBox是在MainViewModel中定义为

的ViewModel
    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();
    }

我的问题是在PortFolioChooserView上我将DataContext设置为null(我有两次调用PortFolioChooserViewModel,一次来自MainViewModel,另一次来自PortFolioChooserView的viewmodel定位器)

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

}

我做错了什么? 感谢

1 个答案:

答案 0 :(得分:0)

  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.