列表框到视图模型属性的数据模板绑定



我正在使用带有DataTemplate的列表框。

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

文本框值已正确绑定。 问题是我的视图模型上有一个名为"ViewMode"的属性,我将文本框的 IsEnabled 属性绑定到 App.xaml 样式数据触发器:

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

这适用于我的所有其他文本框。 如何使 IsEnabled 属性从数据模板中工作?ListBox 的 DataContext 引用了 ViewModel 属性 "Order",所以我认为它应该能够看到 ViewModel 属性 "ViewMode"。

谢谢-希德。

如果你想像

这样进入可视化树,你需要在绑定中使用RelativeSource标记扩展 -

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

默认情况下,您的TextBox DataContext将是您LineQty财产所在的object of OrderLine。因此,样式是在OrderLine对象而不是您的 ViewModel 中搜索ViewMode属性,因此您需要使用 RelativeSource 显式要求它在 UserControl DataContext(即您的ViewModel)中搜索它。

在 DataTemplate 中,您无法直接从 ViewModel 访问属性(您不会"继承"DataContext)。假设您的视图模型是整个视图的 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>

最后,您可以将其用作每个文本框的数据上下文:

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

希望对你有帮助

相关内容

  • 没有找到相关文章

最新更新