/ / DataTrigger neprehodnocuje po zmenách vlastností - wpf, datatemplate, datatrigger

DataTrigger nereevaluuje po zmene vlastností - wpf, datatemplate, datatrigger

[Originál]
mám ListBox ktorý má svoje ItemsSource (to sa deje v kóde zozadu ďalej, ako sa vytvára okno) databázy do ObservableCollection, ListBox potom má nasledovné DataTemplate priradené k položkám:

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>

Kedy sa ObservableCollection je aktualizovaný o objekt, zobrazí sa v ListBox so správnym začiatočným písmenom DataTemplate, keď však hasBeenAnswered vlastnosť nastavená na true (pri ladení vidím, že kolekcia je správna) DataTrigger neprehodnocuje a potom neaktualizuje ListBox používať správne DataTemplate.

Implementoval som INotifyPropertyChanged Udalosť v mojom objekte a ak je v šablóne viazaná na hodnotu, vidím aktualizáciu hodnoty. Je to len to DataTrigger nebude prehodnocovať a meniť na správnu šablónu.

Viem to DataTrigger väzba je správna, pretože ak zavriem okno a znova ho otvorím, bude sa správne aplikovať druhá šablóna údajov, pretože hasBeenAnswered je nastavený na true.

[upraviť 1]
V nadväznosti na komentáre Timores som vyskúšal nasledovné:

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>

Čo sa stane teraz, je podobné ako v prvom príklade,keď je hovor na štítku „Neodpovedané“, zobrazuje sa (jeden na každý hovor, ktorý existuje, pretože ide o zoznam - za normálnych okolností, keď sa načíta okno, nebudú žiadne hovory), hovor sa potom prijme a proptery hasBeenAnswered je nastavený na true, napriek tomu zostáva „Neodpovedané“rovnaký. Ak zavriem okno a znova ho otvorím (pri aktívnom hovore so stále nastavenou vlastnosťou hasBeenAnswered na hodnotu true), bude pozadie modré. Zdá sa mi teda, že dátový spúšťač sa jednoducho nespustí, kým sa okno znovu nespustí.

odpovede:

1 pre odpoveď č. 1

To, čo sa mi v príklade zdá čudné, je, že namiesto ItemTemplate používate ItemContainerStyle.

ItemContainerStyle sa vzťahuje na ListBoxItem, ktorý obsahuje každý prvok vo vašom zdroji ItemsSource. ListboxItem nemá hasBeenAnswered majetok, takže nevidím, ako by väzba mohla fungovať.

Navrhujem vytvoriť DataTemplate pre dátový typ v zozname a použiť spúšťače na vykonanie rovnakých zmien ako vo vašom templateAnswered štýl.

Edit: after OP used the suggestion of ItemTemplate.

Pokúsil som sa reprodukovať príklad a funguje mi to dobre. Tu je môj XAML (prosím ignorujte štýl, toto je iba príklad):

Neodpovedal

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

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

A v kódexe:

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

Môžete to skúsiť zopakovať a porovnať stvoj kód? Poznámka: Vaše správanie môže byť vysvetlené najmenšou chybou v názve vlastnosti, ktorá je uvedená v PropertyChanged. Spúšťač môže byť založený na správnom vlastníctve, ale oznámenie môže mať nesprávne napísaný názov.