用户控件使用错误的DataContext(Usercontrol using wrong Datac

2019-08-01 07:55发布

我有一个是在这样一个家长控制使用的用户控件:

<Views:TranslationTextInput  Translation="{Binding SelectedEntity.Name}"/>

父控制的DataContext是包含SelectedEntity属性一个ViewModel。

在我的孩子我用户控件定义一个新的视图模型作为在DataContext:

    <UserControl.DataContext>
      <vm:TranslationTextInputViewModel x:Name="vm"></vm:TranslationTextInputViewModel>
    </UserControl.DataContext>

在我后面的代码有:

    public static readonly  DependencyProperty TranslationProperty = DependencyProperty.Register("Translation", typeof(Translation),typeof(UserControl));

    // .NET Property wrapper
    public Translation Translation
    {
        get { return (Translation)GetValue(TranslationProperty); }
        set { SetValue(TranslationProperty, value); }
    }


 public TranslationTextInput(){
     InitializeComponent();
     DataContext = new TranslationTextInputViewModel();
     SetBinding(TranslationProperty,   new Binding { Path = new PropertyPath     ("Translation"), Mode = BindingMode.OneWayToSource });

当执行我得到一个绑定错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'SelectedEntity' property not found on 'object' ''TranslationTextInputViewModel' (HashCode=49954236)'. BindingExpression:Path=SelectedEntity.Name; DataItem='TranslationTextInputViewModel' (HashCode=49954236); target element is 'TranslationTextInput' (Name='InputControl'); target property is 'Translation' (type 'Translation')

看来SelectedEntity是抬头对孩子UserControl的视图模型,而应采用父视图模型的财产。 我该如何解决这个问题?

编辑:

    public TranslationTextInputViewModel()
    {
        //EnglishTranslation = tranlsations["en"];
    }

    public string EnglishTranslation
    {
        get
        {
            if (!Translation.TranslationDict.ContainsKey(new CultureInfo("en").LCID))
                Translation.Translations.Add(new TranslationItem() { Text = "", Lcid = new CultureInfo("en").LCID });
            return Translation.TranslationDict[new CultureInfo("en").LCID].Text;
        }
        set
        {
            Translation.TranslationDict[new CultureInfo("en").LCID].Text = value;
        }

    }

    public string SelectedTranslation
    {
        get
        {
            if (!Translation.TranslationDict.ContainsKey(_selectedLanguage))
                Translation.Translations.Add(new TranslationItem() { Text = "", Lcid = _selectedLanguage });
            return Translation.TranslationDict[_selectedLanguage].Text;

        }

        set
        {
            Translation.TranslationDict[_selectedLanguage].Text = value;
        }
    }

    private Translation _translation;

    public Translation Translation
    {
        get
        {
            if (_translation == null)
                _translation = new Translation();
            return _translation; }
        set { _translation = value; }
    }

    private int _selectedLanguage;
    public int SelectedLanguage
    {
        get
        {
            return _selectedLanguage;
        }
    }

    public List<CultureInfo> AvailableLanguages
    {
        get
        {

            return (from x in PqsLocalization.AvailableLanguages where x.Name != "en" select x).ToList();
        }
    }

    public RelayCommand<int> LanguageChanged { get; private set; }


    private void LanguageChangedExecute(int lang)
    {
        _selectedLanguage = lang;
        RaisePropertyChanged("SelectedLanguage");
        RaisePropertyChanged("SelectedTranslation");
    }

Answer 1:

你真的应该绝成不了DataContext一个的UserControl从内部UserControl 。 通过这样做,你是防止任何其他DataContext从获取传递给UserControl ,哪一种失败的WPF最大的有独立的UI层和数据层的优势之一。

当创建你的用户控件,您正在设置DataContext到一个新的TranslationTextInputViewModel ,并TranslationTextInputViewModel没有一个属性调用SelectedEntity ,让你的绑定失败。

我的建议? 不要设置DataContextUserControl

如果要使用特定用户控件的特定视图模型,添加到您的ParentViewModel ,并在将它作为DataContext ,像这样的:

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:TranslationTextInputViewModel}">
        <Views:TranslationTextInput />
    </DataTemplate>
</Window.Resources>

或这个:

<Views:TranslationTextInput 
    DataContext="{Binding SelectedTranslationTextInputViewModel}" />

或者,如果您的ViewModel包含特定的功能, UserControl本身不应该是你的应用程序层的一部分,把这些代码的代码隐藏的UserControl和摆脱的ViewModel完全。



Answer 2:

试试这个:

<Views:TranslationTextInput  Translation="{Binding SelectedEntity.Name}" DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" /> 


Answer 3:

一旦你设置DataContext你的绑定将使用它,所以我希望这个行为-寻找SelectedEntity.NameTranslationTextInputViewModel

有几种方法可以得到这个工作。 就个人而言,我喜欢在视图模型本身(视图模型与视图模型属性)这些关系模式,但在这种情况下,我可能会尝试这一点,因为不愉快的感觉:

<Views:TranslationTextInput 
    Translation="{Binding DataContext.SelectedEntity.Name,
                  RelativeSource={RelativeSource FindAncestor,
                                  AncestorType=ParentControlType}}" />


Answer 4:

这是因为你在构造函数中设置的TranslationTextInput.DataContextTranslationTextInputViewModel。



文章来源: Usercontrol using wrong Datacontext