ビューモデルがあります
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");
}
}
}
ProjectorDisplayControl というコントロール
<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;
}
}
}
このコントロールは 2 つの場所で使用されます。
最初の場所は、うまく機能する 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>
2 番目は、ViewModel オブジェクトを使用してフォームの DataContext を設定したフォームの上にあります。ProjectorDisplayControl が ViewModel で CurrentSelectedProjectionDataElement を消費するようにするには、次のようにする必要があります。
<Window x:Class="Fast_Project.DisplayWindow"
................>
<Viewbox>
<StackPanel>
<controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding CurrentSelectedProjectionDataElement}"/>
</StackPanel>
</Viewbox>
このコードでは、次の 2 つのバインド エラーが発生します。
System.Windows.Data エラー: 40: BindingExpression パス エラー: 'TextBody' プロパティが 'object' ''ViewModel' (HashCode=2512406)' に見つかりません。BindingExpression:Path=TextBody; DataItem='ViewModel' (HashCode=2512406); ターゲット要素は 'TextBlock' (Name='') です。ターゲット プロパティは 'Text' (タイプ 'String') です
System.Windows.Data エラー: 40: BindingExpression パス エラー: 'CurrentSelectedProjectionDataElement' プロパティが 'object' ''ProjectionDataElement' (HashCode=37561097)' に見つかりません。BindingExpression:Path=CurrentSelectedProjectionDataElement; DataItem='ProjectionDataElement' (HashCode=37561097); ターゲット要素は 'ProjectorDisplayControl' (Name='_projectorDisplay') です。ターゲット プロパティは 'ProjectedData' (タイプ 'ProjectionDataElement') です。
DataContext を設定する ProjectorDisplayControl のプライベート プロパティ _projectedData のセッターを見ると、最初に有効な値が設定され、次に null に設定されることがわかります。
単一の ProjectorDisplayControl を保持する DisplayWindow で、CurrentSelectedProjectionDataElement へのバインディングを削除すると、最初のバインディング エラー メッセージのみが表示されます。
<Viewbox>
<StackPanel>
<controls:ProjectorDisplayControl x:Name="_projectorDisplay" />
</StackPanel>
</Viewbox>
最初のバインディング エラーは、DisplayWindow の DataContext が設定されているときに、ProjectorDisplayControl の DataContext が ViewModel オブジェクトで設定されているように感じさせます。しかし、私が読んだことから、コントロールは、設定しない限り、親ウィンドウと同じデータ コンテキストを共有しません。
2 番目のエラー メッセージが示すように、DisplayWindow の ProjectorDisplayControl.ProjectedData のバインディング パスを ProjectionDataElement オブジェクトのように処理しました。
<Viewbox>
<StackPanel>
<controls:ProjectorDisplayControl x:Name="_projectorDisplay" ProjectedData="{Binding }"/>
</StackPanel>
</Viewbox>
それから私に言います:
タイプ 'Fast_Project.ViewModel' と 'Fast_Project.ProjectionDataElement' の間で '一方向' の変換を実行するための既定のコンバーターを作成できません
そもそも思っていたように、本当にViewModelオブジェクトだったように...
とにかく、私の問題の根本は、ProjectorDisplayControl が ViewModel オブジェクトに設定された DataContext をどのように見るかにあると思われます。私がどこを台無しにしたか誰か見ますか?
ご協力ありがとうございました!
解決策は次のとおりです。
プロジェクター表示制御
<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>