如何根据ObservableCollection中INotifyPropertyChanged对象的属性更改Element的属性?

时间:2010-11-12 20:47:04

标签: c# wpf data-binding styles datatrigger

我有一个ObservableCollection<User>个用户对象来实现INotifyPropertyChanged。该集合设置为我的窗口的DataContext,其中包含ListBox(其ItemsSource也设置为相同的集合),多个TextBox es,以及保存Button,标准CRUD设置。

如果User对象的某个属性发生更改,我想更改保存按钮的背景(以及ListBox中与“当前项目”对应的行的背景)。我应该看看风格和触发器吗?

我将以下样式应用于我的保存按钮,而用户对象具有public bool IsDirty属性。

<Style x:Key="PropertyChangedStyle" TargetType="Button">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Source=???, Path=IsDirty}" Value="True">
            <Setter Property="Background" Value="Red" />
        </DataTrigger>
    </Style.Triggers>
</Style>

<Button ... Style="{StaticResource PropertyChangedStyle}">

我认为我走在正确的轨道上,但我不明白如何将绑定指向“设置为datacontext的可观察列表中的当前项目”,其中“当前项目”在这种情况下是由CollectionViewSource.GetDefaultView(ListOfUsers).CurrentItem描述(其中ListOfUsers是我的ObservableCollection<User>)。

2 个答案:

答案 0 :(得分:0)

ListBox中每个项目的DataContext将自动绑定到User个实例,因此无需在绑定中设置源代码。您可以直接从ListBoxItem的样式绑定到User个实例的属性。

你可以这样做:

    <Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="ASD_Answer011.MainWindow"
        x:Name="Window"
        Title="MainWindow"
        Width="640" Height="480">
        <Window.Resources>
            <DataTemplate x:Key="ItemTemplate">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Property1}"/>
                    <CheckBox IsChecked="{Binding Property2}"/>
                </StackPanel>
            </DataTemplate>
            <Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsDirty}" Value="True">
                        <Setter Property="Background" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
                <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
                <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
                <Setter Property="Padding" Value="2,0,0,0"/>
                <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">
                                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsSelected" Value="true">
                                    <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                                </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="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>

        <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource SampleDataSource}}">
            <ListBox ItemTemplate="{DynamicResource ItemTemplate}" ItemsSource="{Binding Collection}" ItemContainerStyle="{DynamicResource ListBoxItemStyle1}"/>
        </Grid>
    </Window>

这是应用程序运行时的外观:

DataTrigger Binding Example

答案 1 :(得分:0)

WPF支持集合中“当前项目”的想法,并将为您跟踪当前项目。您可以编写引用集合当前项的绑定路径。

请参阅MSDN上Data Binding Overview页面上的“当前项目指针”部分。

我在想,如果您的ListBox的ItemsSource被绑定(例如){Binding ListOfUsers},那么您的按钮可以使用{Binding ListOfUsers/IsDirty}

我没有使用过这么多,但我认为您可能必须将ListBox的IsSynchronizedWithCurrentItem属性设置为True才能使其正常工作。