【问题标题】:Change ItemContainerStyle of ListBox MVVM in WPF MVVM Pattern在 WPF MVVM 模式中更改 ListBox MVVM 的 ItemContainerStyle
【发布时间】:2014-12-22 12:10:37
【问题描述】:

我有一个 ListBox,它有一个 itemcontainerstyle,它也有这种风格的背景颜色(比如说绿色),我想从 MVVM 更改背景颜色。 颜色会在某些特定条件下发生变化,否则应使用默认颜色(即绿色)。

<ListBox x:Name="lst1" ItemsSource="{Binding DataSource}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" Style="{DynamicResource StepListBox}" ItemContainerStyle="{DynamicResource ListBoxItemStyle}" Margin="-10,0,0,0">
//Listbox Items
</ListBox>

这是我的 ListboxItemStyle,它在单独的 xaml 文件中定义

<Style x:Key="ListboxItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="Margin" Value="20,0,0,10"/>
        <Setter Property="Background" Value="{DynamicResource Green}"/>
        <Setter Property="BorderBrush" Value="{DynamicResource TertiaryMediumStroke}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Foreground" Value="{DynamicResource SecondaryDark}"/>
        <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="Padding" Value="10,10,0,10"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <Grid Margin="0">
                            <Rectangle x:Name="BgColor" Fill="{DynamicResource TertiaryMediumStroke}" Margin="-10,-10,0,-10" Opacity="0.1"/>
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <!--#FFD1EFD6-->
                            <Setter Property="Background" TargetName="Bd" Value="#FFD7F0DB" />
                            <Setter Property="Opacity" TargetName="BgColor" Value="0" />
                            <Setter Property="Foreground" Value="{DynamicResource ForeLight}"/>
                        </Trigger>
                        <!--
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="true"/>
                                <Condition Property="Selector.IsSelectionActive" Value="false"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                        </MultiTrigger>
                        -->
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Opacity" TargetName="BgColor" Value="0" />
                            <Setter Property="Foreground" Value="{DynamicResource ForeDisable}"/>
                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource TertiaryMedium}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

如何在我的 ViewModel 中更改它?

【问题讨论】:

  • ItemContainerStyle 是一个 UI 元素,与 MVVM 完全无关。也许你应该调整你的标题和/或问题?

标签: wpf mvvm


【解决方案1】:

当使用 MVVM 时,视图模型应该对视图一无所知。但是,如果您真的坚持要从视图模型中更改 UI 元素颜色,那么您可以采用这种方法。这个想法是拥有一个或多个原始类型的属性,例如boolint,甚至enum,它们是在 UI 中绑定的数据。使用DataTriggers,您的 UI 可以“监听”这些属性的变化并相应地更新颜色。举个例子:

如果您只有一种或两种颜色要更新,您可以使用bool 属性和一些DataTriggers:

<Style>
    <Setter Property="Background" Value="White" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsElementRed}" Value="True">
            <Setter Property="Background" Value="Red" />
        </DataTrigger>
    </Style.Triggers>
</Style>

如果您有一系列颜色要更新,您可以使用自定义enum

<Style>
    <Setter Property="Background" Value="White" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding EnumInstance}" Value="SomeValue">
            <Setter Property="Background" Value="Red" />
        </DataTrigger>
        ...
        <DataTrigger Binding="{Binding EnumInstance}" Value="SomeOtherValue">
            <Setter Property="Background" Value="Green" />
        </DataTrigger>
    </Style.Triggers>
</Style>

或者,您也可以使用IValueConverterenum 实例和各种所需颜色之间进行转换。

【讨论】:

    【解决方案2】:

    您只需要在 ViewModel 层的布尔值上的 Style 中的 DataTrigger:

    <Style.Triggers>
        <DataTrigger Binding="{Binding MyBooleanProperty, Mode=OneWay}" Value="True">
            <Setter Property="Background" Value="WhatEverColorYouWant"/>
        </DataTrigger>
    </Style.Triggers>
    <Setter Property="Background" Value="Green"/>
    

    在您的 ViewModel 中:

    public bool MyBool {
        get { return _firstCondition && _secondCondition && _thirdCondition; }
    }
    

    当其中一个条件发生变化时,您只需在 MyBool 上引发 NotifyPropertyChanged

    【讨论】:

    • 谢谢,我有单独的样式表,可以用吗?
    • @SyedSalmanRazaZaidi 不明白。触发器需要在您的 ListboxItemStyle 样式中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 2016-04-10
    • 1970-01-01
    • 2016-07-12
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多