0

DataTemplate で ListBox を使用しています。

                <ListBox Grid.Row="1" Grid.ColumnSpan="3" Grid.RowSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                                ItemsSource="{Binding Order.OrderLines}" >
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition />
                                <RowDefinition />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>

                            <TextBlock Grid.Column="0">Qty</TextBlock>
                            <TextBox Text="{Binding LineQty, Mode=TwoWay}" Grid.Column="1" />

                            <TextBlock Grid.Row="1" Grid.Column="0">Weight</TextBlock>
                            <TextBox Text="{Binding Path=LineWeight}" Grid.Row="1" Grid.Column="1" />

                            <TextBlock Grid.Column="0" Grid.Row="2">Pallet Weights</TextBlock>
                            <TextBox Text="{Binding PalletWeights}" Grid.Row="2" Grid.Column="1" />
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>

            </ListBox>

TextBox 値は適切にバインドされています。問題は、ViewModel に "ViewMode" というプロパティがあり、TextBox の IsEnabled プロパティが App.xaml スタイルの DataTrigger にバインドされていることです。

            <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding ViewMode}" Value="Add">
                    <Setter Property="BorderBrush" Value="White"></Setter>
                    <Setter Property="BorderThickness" Value="2,2,0,0"></Setter>
                    <Setter Property="BorderBrush" Value="Black"></Setter>
                    <Setter Property="BorderThickness" Value="0,0,2,2"></Setter>
                    <Setter Property="Background" Value="LightBlue"></Setter>
                    <Setter Property="Foreground" Value="Black"></Setter>
                    <Setter Property="FontWeight" Value="Bold"></Setter>
                    <Setter Property="IsEnabled" Value="true"></Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding ViewMode}" Value="Edit">
                    <Setter Property="BorderBrush" Value="White"></Setter>
                    <Setter Property="BorderThickness" Value="2,2,0,0"></Setter>
                    <Setter Property="BorderBrush" Value="Black"></Setter>
                    <Setter Property="BorderThickness" Value="0,0,2,2"></Setter>
                    <Setter Property="Background" Value="LightBlue"></Setter>
                    <Setter Property="Foreground" Value="Black"></Setter>
                    <Setter Property="FontWeight" Value="Bold"></Setter>
                    <Setter Property="IsEnabled" Value="true"></Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding ViewMode}" Value="View">
                    <Setter Property="IsEnabled" Value="false"></Setter>
                    <Setter Property="Foreground" Value="Gray"></Setter>
                </DataTrigger>
            </Style.Triggers>
            <Setter Property="Margin" Value="2" />
        </Style>

これは、他のすべての TextBox で機能します。IsEnabled プロパティを DataTemplate 内から機能させるにはどうすればよいですか? ListBox の DataContext は ViewModel プロパティの「Order」を参照しているので、ViewModel プロパティの「ViewMode」を見ることができるはずだと思います。

ありがとう、シド。

4

2 に答える 2

1

DataTemplate内では、ViewModelからプロパティに直接アクセスすることはできません(DataContextを「継承」しません)。ViewModelがビュー全体のDataContextであると仮定すると、プロキシを作成できます。

class BindingProxy : Freezable
{

    #region Freezable Members

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    /// <summary>
    /// Saves the DataContext from the whole view
    /// </summary>
    public object DataContext
    {
        get { return (object)GetValue(DataContextProperty); }
        set { SetValue(DataContextProperty, value); }
    }

    public static readonly DependencyProperty DataContextProperty =
        DependencyProperty.Register("DataContext", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

次に、XAMLファイルで、BindingProxyが配置されている名前空間を参照する必要があります。

<UserControl xmlns:utilities="clr-namespace:MyApp.NamespaceWhereBindingProxyIsLocated"
...

後で、ビューのBindingProxyのインスタンスを作成し、それをビューのDataContextにリンクします(DataContext = {Binding}の部分に注意してください)。

<UserControl.Resources>
   <utilities:BindingProxy x:Key="proxy" DataContext="{Binding}"/>
</UserControl.Resources>

最後に、各TextBoxのDataContextとして使用できます。

<ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        ..
                        <TextBox Text="{Binding Path={TemplateBinding DataContext.LineQty}, Mode=TwoWay}" DataContext="{Binding Source={StaticResource proxy}, Path=DataContext}"/>
                        ..
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>

それが役に立てば幸い

于 2012-11-25T22:14:55.977 に答える
1

RelativeSourceこのようにビジュアル ツリーまで移動する場合は、Binding でマークアップ拡張機能を使用する必要があります。

<DataTrigger Binding="{Binding DataContext.ViewMode,
             RelativeSource={RelativeSource FindAncestor,
                               AncestorType = UserControl}}" 
             Value="Add">
</DataTrigger>

DataContextあなたのTextBox意志のデフォルトobject of OrderLineでは、あなたの財産がLineQty存在する場所です。したがって、スタイルはViewModelViewModeの代わりにオブジェクトのプロパティを検索するため、RelativeSource を使用して、あなたの UserControl で検索するように明示的に要求する必要があります。OrderLineDataContextViewModel

于 2012-11-26T07:09:03.123 に答える