Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF自定义控件拾取父窗口';数据上下文_C#_Wpf_Xaml - Fatal编程技术网

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>