C# WPF自定义控件拾取父窗口';数据上下文
我有一个模型C# WPF自定义控件拾取父窗口';数据上下文,c#,wpf,xaml,C#,Wpf,Xaml,我有一个模型 public class ViewModel:ViewModelObject { public ViewModel() { ProjectionDataElementList = new ObservableCollection<ProjectionDataElement>(); } public ObservableCollection<ProjectionDataElement> ProjectionD
public class ViewModel:ViewModelObject
{
public ViewModel()
{
ProjectionDataElementList = new ObservableCollection<ProjectionDataElement>();
}
public ObservableCollection<ProjectionDataElement> ProjectionDataElementList { get; set; }
private ProjectionDataElement _currentSelectedProjectionDataElement;
public ProjectionDataElement CurrentSelectedProjectionDataElement
{
get
{
return _currentSelectedProjectionDataElement;
}
set
{
_currentSelectedProjectionDataElement = value;
OnPropertyChanged("CurrentSelectedProjectionDataElement");
}
}
}
该控件用于两个位置
第一位是在一个列表框中,它工作得很好:
<ListBox Grid.Column="0" ItemsSource="{Binding Path=ProjectionDataElementList}" Name="projectedDataListBox"
SelectedItem="{Binding Path=CurrentSelectedProjectionDataElement, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Border BorderThickness="1" BorderBrush="Black">
<controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding}"/>
</Border>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
第二个位置是在表单顶部,我用ViewModel对象设置表单的DataContext。要使ProjectOrdSplay控件使用ViewModel中的CurrentSelectedProjectionDataElement,我希望必须执行以下操作:
<Window x:Class="Fast_Project.DisplayWindow"
................>
<Viewbox>
<StackPanel>
<controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding CurrentSelectedProjectionDataElement}"/>
</StackPanel>
</Viewbox>
该代码给了我两个绑定错误:
System.Windows.Data错误:40:
BindingExpression路径错误:
在“对象”“ViewModel”(HashCode=2512406)上找不到“TextBody”属性。
BindingExpression:Path=TextBody;
DataItem='ViewModel'(HashCode=2512406);
目标元素为“TextBlock”(名称=“”);
目标属性为“Text”(类型为“String”)
System.Windows.Data错误:40:
BindingExpression路径错误:
在“对象”“ProjectionDataElement”(HashCode=37561097)上找不到“CurrentSelectedProjectionDataElement”属性。
BindingExpression:Path=CurrentSelectedProjectionDataElement;
DataItem='ProjectionDataElement'(HashCode=37561097);
目标元素是“ProjectOrdSplayControl”(名称=“\u ProjectOrdSplay”);
目标属性为“ProjectedData”(类型为“ProjectionDataElement”)
当我观察设置DataContext的ProjectOrdSplayControl上私有属性_projectedData的setter时,我首先看到它被设置为有效值,然后被设置为null
在保存单个ProjectorDisplay控件的Display窗口中,我可以删除与CurrentSelectedProjectionDataElement的绑定,然后只会收到第一条绑定错误消息:
<Viewbox>
<StackPanel>
<controls:ProjectorDisplayControl x:Name="_projectorDisplay" />
</StackPanel>
</Viewbox>
第一个绑定错误让我感觉,在设置DisplayWindow的DataContext时,ProjectorDisplayControl的DataContext正在使用ViewModel对象进行设置。但从我所读到的内容来看,控件不会与其父窗口共享相同的数据上下文,除非您将其设置为共享
我将DisplayWindow中ProjectOrdSplayControl.ProjectedData的绑定路径视为ProjectionDataElement对象,作为第二条错误消息状态
<Viewbox>
<StackPanel>
<controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding }"/>
</StackPanel>
</Viewbox>
然后他告诉我:
无法创建默认转换器以在“Fast\u Project.ViewModel”和“Fast\u Project.ProjectionDataElement”类型之间执行“单向”转换
就像我一开始以为它是ViewModel对象一样
无论如何,我怀疑问题的根源在于我如何看待将DataContext设置为ViewModel对象的ProjectOrdSplayControl。有人看到我把事情搞砸了吗
谢谢大家的帮助
解决办法是:
项目显示控制
<UserControl x:Class="Fast_Project.ProjectorDisplayControl"
..................>
<Viewbox>
<StackPanel>
<TextBlock Text="{Binding Path=TextBody}"/>
</StackPanel>
</Viewbox>
<StackPanel>
<TextBlock Text="{Binding Path=ProjectedData.TextBody, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:ProjectorDisplayControl}}}"/>
</StackPanel>
显示窗口
<StackPanel>
<controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding Path=ViewModel.CurrentSelectedProjectionDataElement,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:DisplayWindow}}}"/>
</StackPanel>
子控件从其父控件继承依赖项属性值(本例中为DataContext)。 在itemTempalte中使用UserControl时,每个项的DataContext都已经是ProjectionDataElement,因此控件的DataContext设置为ProjectionDataElement 在父控件内使用控件时,它将继承其DataContext 问题是您正在控件上设置ProjectedData属性,而不是在控件内使用它。如果希望每个控件都绑定到ProjectedData上设置的值,则应更新绑定,如下所示:
<UserControl x:Class="Fast_Project.ProjectorDisplayControl"
..................>
<Viewbox>
<StackPanel>
<TextBlock Text="{Binding Path=ProjectedData.TextBody, RelativeSource={RelativeSource Self}"/>
</StackPanel>
对于第二个错误,必须将该窗口的DataContext设置为ProjectionDataElement,这就是在其中搜索它的原因
但从我所读到的内容来看,控件与其父窗口不共享相同的数据上下文,除非您将其设置为相同的数据上下文。
-错误。恰恰相反,除了ItemsControls
(例如ListBox
)之外,每个UI项都与ItemsSource集合中的一个数据项相关联。非常感谢HighCore和nit。你的建议和例子帮助我找到了答案。我已经用固定的XAML更新了我的问题。
<UserControl x:Class="Fast_Project.ProjectorDisplayControl"
..................>
<Viewbox>
<StackPanel>
<TextBlock Text="{Binding Path=ProjectedData.TextBody, RelativeSource={RelativeSource Self}"/>
</StackPanel>