我有一个以这种方式在父控件中使用的UserControl:
<Views:TranslationTextInput Translation="{Binding SelectedEntity.Name}"/>
父控件DataContext是一个包含SelectedEntity属性的ViewModel。
在我的孩子UserControl中,我将新的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 });
执行时我得到一个Binding错误:
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')
似乎在子UserControl的Viewmodel上查找SelectedEntity,但应使用父ViewModel的Property。我该如何解决这个问题?
编辑:
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");
}
答案 0 :(得分:4)
你真的不应该在DataContext
内设置UserControl
的{{1}}。通过这样做,您可以阻止任何其他UserControl
传递给DataContext
,这会破坏WPF拥有单独的UI和数据层的最大优势之一。
创建UserControl时,您将UserControl
设置为新的DataContext
,而TranslationTextInputViewModel
没有名为TranslationTextInputViewModel
的属性,因此您的绑定失败
我的建议?请勿在{{1}}中设置SelectedEntity
。
如果您希望将特定的ViewModel用于特定的UserControl,请将其添加到DataContext
并将其作为UserControl
传递,例如:
ParentViewModel
或者这个:
DataContext
或者,如果您的<Window.Resources>
<DataTemplate DataType="{x:Type vm:TranslationTextInputViewModel}">
<Views:TranslationTextInput />
</DataTemplate>
</Window.Resources>
包含特定于<Views:TranslationTextInput
DataContext="{Binding SelectedTranslationTextInputViewModel}" />
本身的功能且不应该是您的应用层的一部分,请将该代码放在ViewModel
后面的代码中并删除完全是UserControl
。
答案 1 :(得分:1)
试试这个:
<Views:TranslationTextInput Translation="{Binding SelectedEntity.Name}" DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" />
答案 2 :(得分:1)
设置DataContext
后,您的绑定会使用它,所以我希望这种行为 - 在SelectedEntity.Name
上寻找TranslationTextInputViewModel
。
有几种方法可以让它发挥作用。就个人而言,我喜欢在视图模型本身(具有视图模型属性的视图模型)中对这些关系进行建模,但在这种情况下,我可能会尝试这样做,因为感觉不愉快:
<Views:TranslationTextInput
Translation="{Binding DataContext.SelectedEntity.Name,
RelativeSource={RelativeSource FindAncestor,
AncestorType=ParentControlType}}" />
答案 3 :(得分:0)
这是因为您在构造函数中将 TranslationTextInput.DataContext 设置为 TranslationTextInputViewModel 。