5

[原创]
我有一个ListBoxItemsSource(这是在创建窗口时在后面的代码中完成的)数据绑定到一个ObservableCollection. 然后针对这些项目分配ListBox了以下内容:DataTemplate

用户控件.xaml

<ListBox x:Name="communicatorListPhoneControls"
         ItemContainerStyle="{StaticResource templateForCalls}"/>

应用程序.xaml

<Style x:Key="templateForCalls" TargetType="{x:Type ListBoxItem}">  
    <Setter Property="ContentTemplate" Value="{StaticResource templateRinging}"/>  
        <Style.Triggers>  
            <DataTrigger Binding="{Binding Path=hasBeenAnswered}" Value="True">  
                <Setter Property="ContentTemplate" Value="{StaticResource templateAnswered}"/>  
            </DataTrigger>  
        </Style.Triggers>  
    </Setter>
</Style>

ObservableCollection使用对象更新 时,这会出现在ListBox具有正确初始值DataTemplate的 中,但是当hasBeenAnswered属性设置为true(调试时我可以看到集合是正确的)时,DataTrigger不会重新评估然后更新ListBox以使用正确的DataTemplate.

我已经INotifyPropertyChanged在我的对象中实现了事件,如果在模板中绑定了一个值,我可以看到值更新。只是DataTrigger不会重新评估并更改为正确的模板。

我知道DataTrigger绑定是正确的,因为如果我关闭窗口并再次打开它,它将正确应用第二个数据模板,因为hasBeenAnswered设置为true.

[编辑 1]
根据 Timores 的评论,我尝试了以下方法:

用户控件.xaml

<ListBox x:Name="communicatorListPhoneControls"
         ItemTemplate="{StaticResource communicatorCallTemplate}"/>`  

应用程序.xaml:

<DataTemplate x:Key="communicatorCallTemplate">
    <Label x:Name="test">Not answered</Label>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=hasBeenAnswered}" Value="True">
                <Setter TargetName="test" Property="Background" Value="Blue"/>
            </DataTrigger>    
        </DataTemplate.Triggers>
    </Label>
</DataTemplate>

现在发生的情况与第一个示例类似,当“未接听”标签显示来电时(每个呼叫存在一个,因为这是一个列表框 - 通常当窗口加载时不会有呼叫),然后呼叫已回答并且属性hasBeenAnswered设置为 true,但“未回答”保持不变。如果我关闭窗口,然后再次重新打开它(活动调用仍将属性 hasBeenAnswered 设置为 true),则背景为蓝色。所以在我看来,数据触发器根本没有运行,直到窗口重新运行。

4

1 回答 1

1

在示例中,我觉得奇怪的是您使用的是 ItemContainerStyle 而不是 ItemTemplate。

ItemContainerStyle 适用于包含 ItemsSource 中每个元素的 ListBoxItem。ListboxItem 没有hasBeenAnswered属性,所以我看不出绑定是如何工作的。

templateAnswered我建议为列表框中的数据类型创建一个 DataTemplate,并使用触发器进行与您的样式相同的更改。

编辑:在 OP 使用 ItemTemplate 的建议之后。

我试图重现这个例子,它对我来说很好。这是我的 XAML(请忽略样式,这只是一个示例):

没有回答

    <ListBox x:Name="communicatorListPhoneControls" 
             ItemTemplate="{StaticResource communicatorCallTemplate}"/>

    <Button Margin="0,20,0,0" Click="OnToggleAnswer" Content="Toggle answer status" />
</StackPanel>

在代码隐藏中:

public partial class Window1 : Window {

    public Window1() {
        InitializeComponent();

        List<PhoneCall> lpc = new List<PhoneCall>()
        {new PhoneCall(), new PhoneCall(), new PhoneCall(), new PhoneCall()};

        communicatorListPhoneControls.ItemsSource = lpc;
    }

    private void OnToggleAnswer(object sender, RoutedEventArgs e) {

        object o = communicatorListPhoneControls.SelectedItem;

        if (o != null) {

            PhoneCall pc = (PhoneCall) o;
            pc.hasBeenAnswered = ! pc.hasBeenAnswered;
        }
    }
}

public class PhoneCall : INotifyPropertyChanged {

    private bool _answered;


    public bool hasBeenAnswered {
        get { return _answered;  }
        set {
            if (_answered != value) {
                _answered = value;
                FirePropertyChanged("hasBeenAnswered");
            }
        }
    }

    private void FirePropertyChanged(string propName) {

        if (PropertyChanged != null) {

            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

您能否尝试重现此内容并与您的代码进行比较?注意:赋予 PropertyChanged 的​​属性名称中的最小错误可以解释您的行为。触发器可能基于正确的属性,但通知的名称可能拼写错误。

于 2010-03-12T12:24:57.830 回答