用户控件使用错误的DataContext [英] Usercontrol using wrong Datacontext

查看:460
本文介绍了用户控件使用错误的DataContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在父控件使用这样一个用户控件:

 <浏览次数:TranslationTextInput翻译={结合SelectedEntity.Name}/>

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

在我的孩子我的UserControl定义一个新的视图模型作为DataContext的:

 < UserControl.DataContext>
      < VM:TranslationTextInputViewModel X:名称=VM>< / VM:TranslationTextInputViewModel>
    < /UserControl.DataContext>

在code后面我有:

 公共静态只读的DependencyProperty TranslationProperty = DependencyProperty.Register(翻译的typeof(翻译)的typeof(用户控件));    // .NET属性包装
    公共翻译翻译
    {
        {返回(翻译)的GetValue(TranslationProperty); }
        集合{的SetValue(TranslationProperty,值); }
    }
 公共TranslationTextInput(){
     的InitializeComponent();
     的DataContext =新TranslationTextInputViewModel();
     SetBinding(TranslationProperty,新的Binding {路径=新的PropertyPath(翻译),模式= BindingMode.OneWayToSource});

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

  System.Windows.Data错误:40:BindingEx pression路径错误:'SelectedEntity'属性不是'对象'''TranslationTextInputViewModel(哈希code =发现49954236)。 BindingEx pression:路径= SelectedEntity.Name;的DataItem ='TranslationTextInputViewModel'(哈希code = 49954236);目标元素是'TranslationTextInput'(名称='InputControl'); target属性是'翻译'(类型'翻译')

看来SelectedEntity正在抬头对孩子UserControl的视图模型,而应采用父视图模型的财产。我怎样才能解决这个问题?

编辑:

 公共TranslationTextInputViewModel()
    {
        // EnglishTranslation = tranlsations [恩];
    }    公共字符串EnglishTranslation
    {
        得到
        {
            如果(!Translation.TranslationDict.ContainsKey(新的CultureInfo(EN)LCID))
                Translation.Translations.Add(新TranslationItem(){文字=,LCID =新的CultureInfo(EN)LCID});
            返回Translation.TranslationDict [新的CultureInfo(EN)LCID]。文本;
        }
        组
        {
            Translation.TranslationDict [新的CultureInfo(EN)LCID]。文本=价值;
        }    }    公共字符串SelectedTranslation
    {
        得到
        {
            如果(!Translation.TranslationDict.ContainsKey(_selectedLanguage))
                Translation.Translations.Add(新TranslationItem(){文本=,LCID = _selectedLanguage});
            返回Translation.TranslationDict [_selectedLanguage]。文本;        }        组
        {
            Translation.TranslationDict [_selectedLanguage]。文本=价值;
        }
    }    私人翻译_translation;    公共翻译翻译
    {
        得到
        {
            如果(_translation == NULL)
                _translation =新翻译();
            返回_translation; }
        集合{_translation =价值; }
    }    私人诠释_selectedLanguage;
    公众诠释SelectedLanguage
    {
        得到
        {
            返回_selectedLanguage;
        }
    }    公开名单<&的CultureInfo GT; AvailableLanguages
    {
        得到
        {            回报(从X在PqsLocalization.AvailableLanguages​​,其中x.Name =EN选择[x]!).ToList();
        }
    }    公共RelayCommand< INT> LanguageChanged {搞定;私人集; }
    私人无效LanguageChangedExecute(INT郎)
    {
        _selectedLanguage =郎;
        RaisePropertyChanged(SelectedLanguage);
        RaisePropertyChanged(SelectedTranslation);
    }


解决方案

您真的不应该永远设置的DataContext A 的用户控件从里面的用户控件。通过这样做,你是preventing任何其他的DataContext 从获得通过的用户控件,哪一种连败WPF的最大拥有单独的用户界面和数据层的优势之一。

当正在创建的用户控件,您正在设置的DataContext 来一个新的 TranslationTextInputViewModel TranslationTextInputViewModel 没有一个叫做物业 SelectedEntity ,所以你的绑定失败。

我的建议?不要设置的DataContext 用户控件

如果你想使用一个特定的用户控件的特定视图模型,添加到您的 ParentViewModel 并把它作为了的DataContext ,像这样的:

 < Window.Resources>
    <数据类型的DataTemplate ={X:类型VM:TranslationTextInputViewModel}>
        <点击:TranslationTextInput />
    < / DataTemplate中>
< /Window.Resources>

或本

 <浏览次数:TranslationTextInput
    的DataContext ={结合SelectedTranslationTextInputViewModel}/>

或者,如果你的视图模型包含特定于用户控件本身的功能,而不应该是你的应用程序层的一部分,把那个code在code-背后的用户控件和摆脱视图模型干脆。

I have a UserControl that is used in a parent control in this way:

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

The parent control DataContext is a ViewModel containing the SelectedEntity Property.

In my child UserControl I define a new ViewModel as the DataContext:

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

In the code behind I have:

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

When executed I get a Binding error:

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')

It seems the SelectedEntity is looked up on the child UserControl's Viewmodel, but the Property of the parent ViewModel should be used. How can I solve this?

Edit:

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

解决方案

You really shouldn't ever set the DataContext of a UserControl from inside the UserControl. By doing so, you are preventing any other DataContext from getting passed to the UserControl, which kind of defeats one of WPF's biggest advantages of having separate UI and data layers.

When your UserControl is being created, you are setting the DataContext to a new TranslationTextInputViewModel, and TranslationTextInputViewModel does not have a property called SelectedEntity, so your binding fails.

My suggestion? Don't set the DataContext in the UserControl.

If you want a specific ViewModel to be used for a specific UserControl, add that to your ParentViewModel and pass it in as the DataContext, such as this:

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

or this:

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

Or if your ViewModel contains functionality specific to the UserControl itself and should not be part of your application layer, put that code in the code-behind the UserControl and get rid of the ViewModel altogether.

这篇关于用户控件使用错误的DataContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆