/ / DataTrigger wird nach Eigenschaftsänderungen nicht neu bewertet - wpf, datatemplate, datatrigger

DataTrigger wird nach Eigenschaftsänderungen nicht neu bewertet - wpf, datatemplate, datatrigger

[Original]
Ich habe ein ListBox was hat sein ItemsSource (Dies geschieht im Code dahinter beim Erstellen des Fensters) datengebunden an eine ObservableCollection. Das ListBox hat dann folgendes DataTemplate gegen die Elemente zugeordnet:

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>

Wenn das ObservableCollection Wird mit einem Objekt aktualisiert, erscheint dies in der ListBox mit der richtigen Initiale DataTemplatejedoch wenn die hasBeenAnswered Eigenschaft ist festgelegt auf true (Beim Debuggen kann ich sehen, dass die Sammlung korrekt ist) die DataTrigger wird nicht neu bewertet und dann aktualisiert ListBox das richtige verwenden DataTemplate.

Ich habe das implementiert INotifyPropertyChanged Ereignis in meinem Objekt, und wenn in der Vorlage an einen Wert gebunden ist, kann ich die Wertaktualisierung sehen. Es ist nur so, dass die DataTrigger wird nicht neu bewertet und zur richtigen Vorlage geändert.

Ich kenne das DataTrigger Die Bindung ist korrekt, denn wenn ich das Fenster schließe und wieder öffne, wird die zweite Datenvorlage korrekt angewendet, da die hasBeenAnswered ist eingestellt auf true.

[edit 1]
Nach den Kommentaren von Timores habe ich Folgendes versucht:

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>

Was jetzt passiert, ähnelt dem ersten Beispiel:Wenn ein Anruf auf dem Etikett "Nicht beantwortet" eingeht (einer pro vorhandenem Anruf, da es sich um eine Listbox handelt - normalerweise werden beim Laden des Fensters keine Anrufe getätigt), wird der Anruf entgegengenommen und das Proptery hasBeenAnswered ist auf true gesetzt, das "Nicht beantwortet" bleibt jedoch bestehendas Gleiche. Wenn ich das Fenster schließe und es erneut öffne (wobei der aktive Aufruf immer noch mit der Eigenschaft hasBeenAnswered auf true gesetzt ist), ist der Hintergrund blau. Es scheint mir also, dass der Datatrigger einfach nicht ausgeführt wird, bis das Fenster erneut ausgeführt wird.

Antworten:

1 für die Antwort № 1

Was mir im Beispiel seltsam erscheint, ist, dass Sie einen ItemContainerStyle anstelle eines ItemTemplate verwenden.

ItemContainerStyle gilt für das ListBoxItem, das jedes Element in Ihrer ItemsSource enthält. Das ListboxItem hat keine hasBeenAnswered Ich sehe also nicht, wie die Bindung funktionieren könnte.

Ich schlage vor, eine DataTemplate für den Datentyp in Ihrem Listenfeld zu erstellen und Trigger zu verwenden, um dieselben Änderungen wie in Ihrem vorzunehmen templateAnswered Stil.

Bearbeiten: Nachdem OP den Vorschlag der ItemTemplate verwendet hat.

Ich habe versucht, das Beispiel zu reproduzieren, und es funktioniert gut für mich. Hier ist meine XAML (bitte ignorieren Sie den Stil, dies ist nur ein Beispiel):

Nicht beantwortet

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

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

Und im Code-Behind:

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;
}

Könnten Sie versuchen, dies zu reproduzieren und mit zu vergleichendein Code ? Hinweis: Der kleinste Fehler im Eigenschaftsnamen, der PropertyChanged zugewiesen wurde, kann Ihr Verhalten erklären. Der Auslöser könnte auf der richtigen Eigenschaft basieren, aber die Benachrichtigung könnte einen falsch geschriebenen Namen haben.