5

[元の]
データがにバインドされ てListBoxいるItemsSource(これは、ウィンドウが作成されるときにコードビハインドで行われます)ObservableCollection。次に、アイテムに対してListBox以下がDataTemplate割り当てられます。

usercontrol.xaml

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

app.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がに設定されているため、2番目のデータテンプレートが正しく適用されるため、バインディングが正しいことがわかりますtrue

[編集1]
Timoresによるコメントに続いて、私は次のことを試みました。

usercontrol.xaml

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

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

ここで発生するのは最初の例と同様です。「未応答」ラベルに電話がかかってくると(これはリストボックスであるため、電話ごとに1つあります。通常、ウィンドウが読み込まれると電話はありません)、電話は次のようになります。回答済みで、プロパティhasBeenAnsweredはtrueに設定されていますが、「未回答」は同じままです。ウィンドウを閉じて再度開くと(プロパティhasBeenAnsweredがtrueに設定されたままのアクティブな呼び出しで)、背景は青色になります。したがって、ウィンドウが再実行されるまで、データトリガーは単に実行されていないように見えます。

4

1 に答える 1

1

この例で私には奇妙に思えるのは、ItemTemplateの代わりにItemContainerStyleを使用していることです。

ItemContainerStyleは、ItemsSourceの各要素を含むListBoxItemに適用されます。ListboxItemにはhasBeenAnsweredプロパティがないため、バインディングがどのように機能するかわかりません。

リストボックスにデータ型のDataTemplateを作成し、トリガーを使用してスタイルと同じ変更を加えることをお勧めしますtemplateAnswered

編集: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 に答える