Hallo,
ich habe eine ObservableCollection<MyObject> als Property in meinem DataContext.
Leider kann ich bei MyObject das INotifyPropertyChanged nicht implementieren, wesshalb ich das Binding manuell "refreshen" möchte.
Gebunden ist in XAML so:
DataContext="{Binding Path=.}" ItemsSource="{Binding Path=Prop}"
bisher habe ich folgendes schon gefunden/versucht:
listview.GetBindingExpression(ListView.ItemsSourceProperty).UpdateTarget()
leider tut sich dabei garnichts. (mit ListView.DataContextProperty leider auch nicht)
hat noch wer Ideen?
prinzipiell gibt es für bindings eine art, das ganze manuell zu refreshen,
und zwar über den UpdateSourceTrigger.
hier ein kleines beispiel
<TextBox x:name="TextBox" Text="{Binding Path=Text, UpdateSourceTrigger=Explicit}" />
BindingExpression be = TextBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
so funktioniert es im normalfall 😉
Ja, genau das beispiel findet sich überall.
Nur welches ist das richtige Property für das ListView?
Als "workaround" klappt den DataContext auf null anschließend wieder setzten. Aber ich glaube noch schmutziger gehts wohl nicht 😉
Hallo,
ich habe eine ObservableCollection<MyObject> als Property in meinem DataContext.Leider kann ich bei MyObject das INotifyPropertyChanged nicht implementieren, wesshalb ich das Binding manuell "refreshen" möchte.
Gebunden ist in XAML so:
DataContext="{Binding Path=.}" ItemsSource="{Binding Path=Prop}"
bisher habe ich folgendes schon gefunden/versucht:
listview.GetBindingExpression(ListView.ItemsSourceProperty).UpdateTarget()
leider tut sich dabei garnichts. (mit ListView.DataContextProperty leider auch nicht)
hat noch wer Ideen?
hi ,
ja ich hab ne idee
kapsel das MyObject selber nochmal weg und arbeite nur noch darrueber
class MyObject {} <-- das objekt was du binden willst aber nicht aendern kannst
class MyObjectViewModel : INotifyPropertyChanged
{
private MyObject _innerObject { get; set; }
public MyObjectViewModel(MyObject innerObject)
{
_innerObject = innerObject
}
public string Name
{
get { return _innerObject.Name; }
set
{
_innerObject.Name = value;
OnPropertyChanged(this, "Name");
}
}
}
ist das ganz normale MVVM prinzip
Hallo,
danke. Genau so hab ich das schon. Nur wenn ich jetzt das innerObject aus der Datenbank refreshe, werden eben nicht die Setter in MyObjectViewModel aufgerufen sondern nur das innerObject aktualisiert.
/edit
hier mal mein Beispiel vollständig:
public class MyObj
{
public string Name { get; set; }
}
public class Src : INotifyPropertyChanged
{
public ObservableCollection<MyObj> Prop { get; set; }
public void Changed()
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Prop"));
}
public event PropertyChangedEventHandler PropertyChanged;
}
XAML:
<ListView Grid.Row="0" DataContext="{Binding Path=.}" ItemsSource="{Binding Path=Prop}" Name="listView" >
<ListView.View>
<GridView>
<GridViewColumn Header="Number Plate" DisplayMemberBinding="{Binding Path=Name}" />
</GridView>
</ListView.View>
</ListView>
<Button Height="23" Click="button1_Click">Button</Button>
und Code Behind des Windows:
public partial class Window1 : Window
{
Src src = new Src();
public Window1()
{
InitializeComponent();
src.Prop = new ObservableCollection<MyObj>();
src.Prop.Add(new MyObj() { Name = "item1" });
src.Prop.Add(new MyObj() { Name = "item2" });
src.Prop.Add(new MyObj() { Name = "item3" });
src.Prop.Add(new MyObj() { Name = "item4" });
this.DataContext = src;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
src.Prop[2].Name = "! changed item !";
src.Changed();
}
}
Wo hab ich hier nen Denkfehler? 🙁
MyObj muss auch INotifyPropertyChanged implementieren.
Du änderst ja auch ein Objekt in der Liste und nicht die Liste selbst.
Hallo,
danke. Genau so hab ich das schon.
nein hast du nicht
du hast die gesamte liste gekapselt - das ist quatsch, das macht ObservableCollection bereits
du musst dein "MyObj" selber kapseln und das dann in der liste verwenden
class MyObj
class MyObjViewModel ... (inner = MyObj)
public ObservableCollection<MyObjViewModel> ...
Ok, stimmt natürlich.
Ändert aber nichts daran, dass _innerMyObj direkt aktualisiert (NhibernateSession.Refresh(..)) wird und die Setter aus dem MyObjViewModel nicht aufgerufen werden.
Es sei denn, ich frag das Objekt neu aus der Datenbank ab und setze Property für Property, was ich mir eigentlich sparen wollte mit einem Binding Refresh 😃
... Setter aus dem MyObjViewModel nicht aufgerufen werden.
Das ist das Problem. Woher soll das Binding dann wissen dass es aktualisiert werden muss?
Leider kann ich bei MyObject das INotifyPropertyChanged nicht implementieren
warum eigentlich nicht? Hibernate steht da nicht im Weg.
Das ist das Problem. Woher soll das Binding dann wissen dass es aktualisiert werden muss?
Desshalb möchte ich es ja manuell tun 😃
Das einzigste was bisher funktioniert hat war
DataContext = null;
DataContext = src;
warum eigentlich nicht? Hibernate steht da nicht im Weg.
Weil die Datenobjekte lediglich die Properites ohne zusätzliche Dinge enthalten sollen. Desshalb hab ich ja entsprechende ViewModels.
ach kinder - werdet mal erwachsen #gg
wenn du eine "Refresh" methode hast welche das neue "_innerMyObj" aktualisiert, trigger doch einfach alle notwendigen propertychanges an und feddich is
public void Refresh(MyObj newObj)
{
_innerMyObj = newObj;
OnPropertyChanged(this, "Name");
OnPropertyChanged(this, "Value");
OnPropertyChanged(this, "ScheissenDreck");
}
dann liest die ui diese aufgelisteten properties neu
Du hast dich für den unbequemen Weg entschieden. 😃
Lösungsmöglichkeiten sind genug gepostet worden.
das es geht heisst nicht das es auch "richtig" ist {o;
btw
ein neues model erfordert ein neues viewmodel! soviel zum thema "refresh"
wenn du ein neues innerobjekt hast - entferne das komplette viewmodel und pack ein neues rein - aus die maus