[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 DataTemplate
jedoch 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 № 1Was 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.