【问题标题】:How to set the background color of textblocks in a listbox?如何在列表框中设置文本块的背景颜色?
【发布时间】:2019-09-17 08:04:02
【问题描述】:

我的问题是为什么 Textblock Background={Binding IsActive} 部分不刷文本块,但是 - 当我将列表框背景颜色绑定到 IsActive 时 - 列表框背景是红色的。我只需要为item.Activatedfalse 的列表框中的每个项目着色。

这是我的代码:

Xaml:

 <ListBox
  Grid.Row="1" 
  Background="{Binding IsActive}"
  ItemsSource="{Binding AllProjects}"
  SelectedItem="{Binding SelectedProject}"
  Margin="0 5">
        <ListBox.ItemTemplate >
            <DataTemplate >
                <TextBlock Background="{Binding IsActive}">
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}{0} - {1}">
                            <Binding Path="OrderName" />
                            <Binding Path="OrderNumber" />
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

MVVM:

private Brush _isactive;

public Brush IsActive
{
    get => _isactive;
    set
    {
        _isactive = value;
        RaisePropertyChanged("IsActive");
    }
}

private void ColorBackground()
{
    foreach (var item in AllProjects)
    {
        if (item.Activated == false)
        {
            IsActive = (Brush)new BrushConverter().ConvertFromString("Red");
        }
    }
}

【问题讨论】:

  • 你违反了 MVVM 规则。您的视图模型具有Brush 类型的属性。这是错误的 - 这是一个表示方面,应该由视图处理。您的视图模型已经有一个属性bool Activated。您的视图应该定义一个 DataTrigger 并根据该属性值将背景设置为所需的颜色。

标签: c# wpf mvvm data-binding


【解决方案1】:

为什么它不起作用

ListBox 正在其DataContext 对象中寻找IsActive 属性。它似乎找到了它,因为您的 ListBox 得到了正确的颜色。

但是,ListBox(以及所有TextBlocks)中生成的每个项目都有一个不同的DataContext,它似乎没有IsActive 属性。

肮脏的解决方案

IsActive 属性从ListBoxDataContext 移动到每个项目DataContext(我假设您有某种ProjectViewModel?)。 请注意,这违反了 MVVM,因为 ViewModel 不应该知道任何有关特定视图细节(如背景颜色)的信息。

MVVM 解决方案

  1. 要么不执行任何Binding 并将您的背景颜色定义为资源,然后使用StaticResource 标记在您的XAML 中引用它们。这要好得多,因为与视图相关的任何内容都保留在视图中,但这不会让您的颜色根据您的数据而改变。这将给出这样的 XAML:
<Window.Resources>
    <ResourceDictionary>
        <SolidColorBrush x:Key="IsActiveBrush" Color="Red"/>
        <SolidColorBrush x:Key="IsInactiveBrush" Color="Blue"/>
    </ResourceDictionary>
</Window.Resources>
<!--...-->
<DataTemplate>
    <!--All your TextBlocks have the same color-->
    <TextBlock Background="{StaticResource IsInactiveBrush}">
        <TextBlock.Text>
        ...
        </TextBlock.Text>
    </TextBlock>
</DataTemplate>

  1. 最好的选择是定义一个 DataTemplate,它会根据 Activated 布尔属性自动更改背景颜色,如下所示,使用触发器:
<DataTemplate>
    <TextBlock>
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <!--Default background of blue-->
                <Setter Property="Background" Value="Blue"></Setter>
                <Style.Triggers>
                    <!--Change background to red when Activated is true-->
                    <DataTrigger Binding="{Binding Activated}" Value="True">
                        <Setter Property="Background" Value="Red"></Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
        <TextBlock.Text>
        ...
        </TextBlock.Text>
    </TextBlock>
</DataTemplate>

无论如何,您都会从您的 ViewModel 中删除任何 Brush 引用并仅保留布尔值 Activated 属性。

如果您结合选项 2. 和 3.,您可以将 Setters 替换为:

<Setter Property="Background" Value="{StaticResource IsInactiveBrush}"></Setter>
...
<Setter Property="Background" Value="{StaticResource IsActiveBrush}"></Setter>

【讨论】:

  • 感谢您的回答和解释:)
猜你喜欢
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
相关资源
最近更新 更多