1

WindowとUserControlがあります。UserControlは、次のような独自のビューモデルを作成します。

<UserControl x:Class="UiInteraction.UserControl3"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:UiInteraction"
             mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.DataContext>
        <local:UserControl3Vm/>
    </UserControl.DataContext>

    <StackPanel>
        <TextBlock Text="{Binding String1}"/>
    </StackPanel>

</UserControl>

WindowがUserControlをインスタンス化するとき、WindowのビューモデルがUserControlのビューモデルを取得できるようにしたい。

<Window x:Class="UiInteraction.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:UiInteraction"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:MainWindowVm/>
    </Window.DataContext>

    <StackPanel>
        <local:UserControl3 DataContext="{Binding UserControl3Vm, Mode=OneWayToSource}"/>
    </StackPanel>

</Window>

Windowのviewmodelには、オブジェクト型の公的に設定可能なプロパティがあります。DataContextバインディングを使用すると、UserControl3が作成されると、そのDataContextの値(ビューモデルへの参照)がウィンドウのビューモデルのUserControl3Vmプロパティに割り当てられることを期待しています。

実際に発生するのは、Window.UserControl3Vmプロパティセッターが値nullで呼び出されることです。

なぜこれが起こっているのですか、そして私が考えていることを達成するための最良の方法は何ですか?

ユーザーコントロールのビューモデルをウィンドウのビューモデルのプロパティとしてインスタンス化し、ユーザーコントロールをそれにバインドする方が簡単だと思います(これにより、ビューとビューモデルの結合も最小限に抑えられます)。しかし、私が働いている場所では、彼らは少し厄介で、ビューモデルを最初に作成するのではなく、ビューを最初にMVVMを好むので、ビューモデルがビューによって作成されるときに、ビューモデルが効果的にコラボレーションできるようにする最も分離された方法を探しています。

4

2 に答える 2

2

OneWayToSourceコードビハインドなしでバインディングを使用することは機能しないと思います。

最初は、UserControl.DataContextのインスタンスに設定されていますが、BindingにUserControl3vm置き換えているため、元のインスタンスはどこにも参照されなくなります。UserControl3vmUserControl3vm

OneWayToSourceバインディングを機能させるには、最初にをバインディングに設定してからDataContextOneWayToSourceバインディングのソースをUserControl3vmUserControl内からの新しいインスタンスに設定する必要があります。

私の記憶が正しければ、BindingOperations.GetBindingExpressionを使用してバインディングを取得し、そのDataItemプロパティを更新できます。バインディングUserControl.DataContextが上書きされるため、単純に設定することはできません。OneWayToSource

個人的には、コードでそれを行うだけです-Loadedイベントの背後にあります

彼らがView-FirstMVVMを主張している場合、Viewはアプリケーションフローを制御しており、アプリケーションロジックをViewのコードビハインドから除外する必要がある理由はわかりません。

したがって、LoadedイベントでWindow.DataContext.UserControl3VmプロパティをUserControl3.DataContextに設定するだけです:)

<Window x:Name="MyWindow"
        Loaded="MyWindow_Loaded" 
        ... >
    <StackPanel>
        <local:UserControl3 x:Name="MyUserControl" />
    </StackPanel>
</Window>

void MyWindow_Loaded(object sender, EventArgs e)
{
    ((MainWindowVm)MyWindow.DataContext).UserControl3Vm 
        = MyUserControl.DataContext;
}
于 2013-01-09T15:18:50.960 に答える
0

これは、XAMLでいくつかの回避策(DataContextホスト要素のアクセスをハックするため)を使用して可能です。アプローチはここで言及されています。Freezablesを使用しています。

XAMLは

<Window x:Class="VM2VMBindingInXaml.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vw="clr-namespace:VM2VMBindingInXaml.View"
        xmlns:vm="clr-namespace:VM2VMBindingInXaml.ViewModel"
        Title="MainWindow" Height="350" Width="525" >
    <Window.Resources>
             <vm:UserControl1ViewModel x:Key="childVM"></vm:UserControl1ViewModel>
        <vm:DataResource x:Key="childVmBinding" BindingTarget="{Binding ElementName=child, Path=DataContext}"/>
    </Window.Resources>
    <Window.DataContext>
        <vm:MainWindowViewModel x:Name="mainViewModel" >
            <vm:MainWindowViewModel.ChildViewModel>
                <vm:DataResourceBinding DataResource="{StaticResource childVmBinding}">

                </vm:DataResourceBinding>
            </vm:MainWindowViewModel.ChildViewModel>
        </vm:MainWindowViewModel>
    </Window.DataContext>
    <Grid>
        <vw:UserControl1 x:Name="child" DataContext="{Binding Source={StaticResource ResourceKey=childVM}}">
        </vw:UserControl1>
    </Grid>
</Window>
于 2013-01-10T03:31:32.610 に答える