2013-09-26 36 views
0

我有一个名为ProjectorDisplayControlWPF自定义控件端起碗父窗口的DataContext的

<UserControl x:Class="Fast_Project.ProjectorDisplayControl" 
     ..................> 
<Viewbox> 
    <StackPanel> 
     <TextBlock Text="{Binding Path=TextBody}"/> 
    </StackPanel> 
</Viewbox> 

public partial class ProjectorDisplayControl : UserControl 
{ 

    public ProjectorDisplayControl() 
    { 
     InitializeComponent(); 
    } 

    public static readonly DependencyProperty ProjectedDataProperty = DependencyProperty.Register("ProjectedData", typeof(ProjectionDataElement), typeof(ProjectorDisplayControl), 
      new PropertyMetadata(new PropertyChangedCallback((objectInstance, arguments) => 
      { 
       ProjectorDisplayControl projectorDisplayControl = (ProjectorDisplayControl)objectInstance; 
       projectorDisplayControl._projectedData = (ProjectionDataElement)arguments.NewValue; 
      }))); 

    public ProjectionDataElement ProjectedData 
    { 
     get 
     { 
      return (ProjectionDataElement)GetValue(ProjectedDataProperty); 
     } 
     set 
     { 
      SetValue(ProjectedDataProperty, value); 
     } 
    } 


    private ProjectionDataElement _projectedData 
    { 
     get 
     { 
      return this.DataContext as ProjectionDataElement; 
     } 
     set 
     { 
      this.DataContext = value; 
     } 
    } 
} 

一个ViewModel

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它的伟大工程:

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

第二位的是,我设置窗体的DataContext的一个视图模型对象的窗体的顶部。为了使ProjectorDisplayControl消耗视图模型的CurrentSelectedProjectionDataElement我希望有这样做:

<Window x:Class="Fast_Project.DisplayWindow" 
    ................> 
<Viewbox> 
    <StackPanel> 
     <controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding CurrentSelectedProjectionDataElement}"/> 
    </StackPanel> 
</Viewbox> 

该代码给了我两个绑定错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'TextBody' property not found on 'object' ''ViewModel' (HashCode=2512406)'. BindingExpression:Path=TextBody; DataItem='ViewModel' (HashCode=2512406); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

System.Windows.Data Error: 40 : BindingExpression path error: 'CurrentSelectedProjectionDataElement' property not found on 'object' ''ProjectionDataElement' (HashCode=37561097)'. BindingExpression:Path=CurrentSelectedProjectionDataElement; DataItem='ProjectionDataElement' (HashCode=37561097); target element is 'ProjectorDisplayControl' (Name='_projectorDisplay'); target property is 'ProjectedData' (type 'ProjectionDataElement')

当我看二传手在ProjectorDisplayControl私有财产_projectedData其设置的DataContext我第一次看到它都将置有一个有效的值,然后设置为null。

在持有单ProjectorDisplayControl我可以删除绑定到CurrentSelectedProjectionDataElement,然后我只得到了第一个绑定错误消息DisplayWindow:

<Viewbox> 
    <StackPanel> 
     <controls:ProjectorDisplayControl x:Name="_projectorDisplay" /> 
    </StackPanel> 
</Viewbox> 

第一装订错误让我感觉像ProjectorDisplayControl的DataContext的是当DisplayWindow的DataContext被设置时,使用ViewModel对象进行设置。但是从我读过的控件中,除非你设置它,否则不要与它们的父窗口共享相同的数据上下文。

我已经处理为ProjectorDisplayControl.ProjectedData结合路径中DisplayWindow就像是一个ProjectionDataElement对象作为第二错误消息的状态。

<Viewbox> 
    <StackPanel> 
     <controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding }"/> 
    </StackPanel> 
</Viewbox> 

然后告诉我:

Cannot create default converter to perform 'one-way' conversions between types 'Fast_Project.ViewModel' and 'Fast_Project.ProjectionDataElement'

像果然是视图模型对象就像我认为这是摆在首位...

反正我怀疑的我的根问题就出在我所看到有一个DataContext设置为视图模型对象ProjectorDisplayControl。任何人都看到我搞乱了吗?

谢谢大家的帮助!


将溶液:


ProjectorDisplayControl

 <StackPanel> 
     <TextBlock Text="{Binding Path=ProjectedData.TextBody, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:ProjectorDisplayControl}}}"/> 
    </StackPanel> 

DisplayWindow

<StackPanel> 
     <controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding Path=ViewModel.CurrentSelectedProjectionDataElement, 
      RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:DisplayWindow}}}"/> 
    </StackPanel> 
+0

'但是从我读过的控制,除非你把它so.'不同意他们的父窗口相同的数据上下文 - 错误。它恰恰相反,除了'ItemsControls'(例如'ListBox'),其中每个UI项目都与ItemsSource集合中的一个数据项目相关联。 –

回答

0

儿童控制继承了依赖属性值(或DataContext的在这种情况下)从ir父母。 当您在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那是为什么在里面搜索它。

+0

非常感谢HighCore和nit。你的建议和例子帮助我找出答案。我用固定的XAML更新了我的问题。 –