WPF绑定和资源查找的复杂性

WPF绑定和资源查找的复杂性,wpf,xaml,data-binding,mvvm,Wpf,Xaml,Data Binding,Mvvm,我有一个内容控件,如下所示: <ContentControl x:Name="grid1ContentControl" Content="{Binding MainGridViewModel}" /> <DataTemplate DataType="{x:Type App:MainGridViewModelType}">... 我一直遇到同样的问题。在我的理解中,在可视化初始化之后,框架对绑定属性的后续赋值的反应是有差距的。我采纳了威尔的建议,开发了一个原型,如下所

我有一个内容控件,如下所示:

<ContentControl x:Name="grid1ContentControl" Content="{Binding MainGridViewModel}" />
<DataTemplate DataType="{x:Type App:MainGridViewModelType}">...

我一直遇到同样的问题。在我的理解中,在可视化初始化之后,框架对绑定属性的后续赋值的反应是有差距的。我采纳了威尔的建议,开发了一个原型,如下所述。我很感激你的进一步想法

这里有一个关于这个问题的报告。这是一本书

以下是主窗口代码,为进一步讨论提供上下文。在原型项目中,NewTabControlViaContentControlCommand起作用,而NewTabControlCommand不起作用

MainWindow.xaml:

    <Window x:Class="DynamicTabControlSimpleProto.View.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:DynamicTabControlSimpleProto.ViewModel"
        xmlns:vw="clr-namespace:DynamicTabControlSimpleProto.View"
        xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
        mc:Ignorable="d"
        Height="300"
        Width="500"
        Title="Dynamic TabControl Prototype"
        DataContext="{Binding Main, Source={StaticResource Locator}}">

    <Window.Resources>
        <DataTemplate DataType="{x:Type vm:TabControlViewModel}">
            <vw:TabControlUserControl />
        </DataTemplate>

        <DataTemplate x:Key="tabControlDataTemplate">
            <vw:TabControlUserControl />
        </DataTemplate>

    </Window.Resources>

    <Grid x:Name="LayoutRoot">

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="4" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <StackPanel Name="stackPanel" Grid.Column="0">
            <Button
                Content="NewTabControl" 
                Command="{Binding NewTabControlCommand}"
                CommandParameter="{Binding Path=DataContext}" />

            <Button
                Content="NewTabControlViaContentControl" 
                Command="{Binding NewTabControlViaContentControlCommand}"
                CommandParameter="{Binding ElementName=tabControlContentControl}" />
        </StackPanel>

        <DockPanel
            Name="dockPanel"
            Grid.Column="2">
            <Border 
                BorderBrush="Blue"
                BorderThickness="5">
                <ContentControl x:Name="tabControlContentControl" DataContext="{Binding TabControlViewModel, diag:PresentationTraceSources.TraceLevel=High}" />
            </Border>
        </DockPanel>
    </Grid>
</Window>
<Window DataContext="{Binding Source={StaticResource MainViewModel}}" ...>

MainWindowViewModel.cs

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Windows.Controls;
using DynamicTabControlSimpleProto.View;
using System.Windows;

namespace DynamicTabControlSimpleProto.ViewModel
{

    public class MainViewModel : ViewModelBase
    {
        public string Welcome
        {
            get
            {
                return "Welcome to MVVM Light";
            }
        }

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            NewTabControlCommand = new RelayCommand<object>(obj =>
                {
                    this.NewTabControl(obj);
                });

            NewTabControlViaContentControlCommand = 
                new RelayCommand<ContentControl>(tabControlContentControl =>
                {
                    this.NewTabControlViaContentControl(tabControlContentControl);
                });


        }

        public TabControlViewModel TabControlViewModel
        {
            get
            {
                return _tabControlViewModel;
            }
            private set
            {
                _tabControlViewModel = value;
                RaisePropertyChanged("TabControlViewModel");
            }
        }

        public RelayCommand<object> NewTabControlCommand
        {
            get;
            private set;
        }

        private TabControlViewModel _tabControlViewModel = null;

        void NewTabControl(object obj)
        {
            TabControlViewModel = new TabControlViewModel();
        }

        public RelayCommand<ContentControl> NewTabControlViaContentControlCommand
        {
            get;
            set;
        }

        void NewTabControlViaContentControl(ContentControl tabContentControl)
        {
            TabControlViewModel = new TabControlViewModel();
            MainWindow mwin = Application.Current.MainWindow as MainWindow;
            tabContentControl.SetValue(ContentControl.ContentTemplateProperty, mwin.FindResource("tabControlDataTemplate") as DataTemplate);
        }



    }
}
使用GalaSoft.MvvmLight;
使用GalaSoft.MvvmLight.Command;
使用System.Windows.Controls;
使用DynamicTabControlSimpleProto.View;
使用System.Windows;
命名空间DynamicTableControlSimpleProto.ViewModel
{
公共类MainViewModel:ViewModelBase
{
公众欢迎
{
得到
{
返回“欢迎使用MVVM灯”;
}
}
/// 
///初始化MainViewModel类的新实例。
/// 
公共主视图模型()
{
NewTabControlCommand=new RelayCommand(obj=>
{
这是一个新的控制(obj);
});
NewTabControlViaContentControlCommand=
新建RelayCommand(tabControlContentControl=>
{
此.NewTabControlViaContentControl(tabControlContentControl);
});
}
公共选项卡ControlViewModel选项卡ControlViewModel
{
得到
{
返回选项卡ControlViewModel;
}
专用设备
{
_tabControlViewModel=值;
RaisePropertyChanged(“TabControlViewModel”);
}
}
公共中继命令NewTabControlCommand
{
得到;
私人设置;
}
私有TabControlViewModel\u TabControlViewModel=null;
无效控件(对象对象对象)
{
TabControlViewModel=新的TabControlViewModel();
}
public relay命令newtabcontrolvia contentcontrolcommand
{
得到;
设置
}
void newtabcontrolvia ContentControl(ContentControl选项卡ContentControl)
{
TabControlViewModel=新的TabControlViewModel();
MainWindow mwin=Application.Current.MainWindow作为主窗口;
tabContentControl.SetValue(ContentControl.ContentTemplateProperty,mwin.FindResource(“tabControlDataTemplate”)作为DataTemplate);
}
}
}

我相信我在上述不起作用的技术中发现了错误。我是通过尝试直接在XAML中设置DataContext找到它的,方法与我在代码中所做的相同,即直接设置为ViewModel。当我尝试这个的时候,它也不起作用

例如,将my Main窗口的DataContext设置为ViewModel不起作用:

<Window DataContext="vm:MainViewModel" ...>

但是,将我的窗口的DataContext设置为在更高级别组件的参考资料中声明的ViewModel(在我的示例中为App.xaml),可以让一切正常工作:

在App.xaml中:

<Application.Resources>
    <vm:MainViewModel x:Key="MainViewModel" />
</Application.Resources>

我相信我在上述不起作用的技术中发现了错误。我是通过尝试直接在XAML中设置DataContext找到它的,方法与我在代码中所做的相同,即直接设置为ViewModel。当我尝试这个的时候,它也不起作用

例如,将my Main窗口的DataContext设置为ViewModel不起作用:

<Window DataContext="vm:MainViewModel" ...>

但是,将我的窗口的DataContext设置为在更高级别组件的参考资料中声明的ViewModel(在我的示例中为App.xaml),可以让一切正常工作:

在App.xaml中:

<Application.Resources>
    <vm:MainViewModel x:Key="MainViewModel" />
</Application.Resources>

为什么?可能是数百个原因之一。MainGridViewModel是否是ContentControl的DataContext上设置的实例的属性?在构造函数中调用InitializeComponent之前,您是否执行了所有这些操作?等等等等。您需要创建尽可能最简单的、可编译的原型,以满足您的需要,并查看是否可以重新编写您的问题。然后用这里的代码(有问题的代码,请不要链接)来说明你的问题。但是您很可能会自己解决问题。@威尔:是的,MainGridViewModel是ContentControl的DataContext实例的属性。调用InitializeComponent后会设置MainGridViewModel。框架没有第一次“应用数据模板”;MainGridViewModel的后续设置具有预期效果。我将尝试创造一个简单的复制品;看起来我需要重新触发绑定,或者,可能需要添加一个新绑定来获取ContentControl,以便将类型链接的DataTemplate添加到其ContentPresenter,就像直接设置ContentControl.ContentTemplateProperty一样。您所说的让我相信它应该可以工作。我已经做过很多次了。我想你的原型会澄清你的问题。@will:嗨,will,我接受了你的建议并制作了一个原型。这真的很简单,并且说明了这两种技术并没有像我预期的那样起作用,也说明了这一技术确实起作用。我在原始帖子中添加了一个VS2010编译项目的链接,并添加了代码和简要说明,以便为讨论提供上下文。我非常感谢您提供的任何其他见解。谢谢,酷。我明天去看看。为什么?可能是数百个原因之一。MainGridViewModel是否是在数据库的DataContext上设置的实例的属性