aber das Binding wird zwar bei der Initialisierung abgefragt, ignoriert
aber spätere Änderungen...
ein Direktzugriff auf TextBlock1.Text = "blah" bekomme ich ja aus einer
Statischen Methode nicht...
Vielen Dank für jeden Tipp
bärnd
Hallo, wieso statisches Binding?
Wenn du das MVVM Pattern benutzt, dann kannst Du deine Eigenschaft
einfach binden.
1
publicstringText{get;set;}
Natürlich müsstest Du in dem ViewModel das INotifiyPropertChanged
implementieren und oben wie in meinem Beispiel Fody.PropertyChanged für
das AutoProperty.
naja, es geht nicht um den Static wert, sondern um meine Methode welche
Statisch sein muss... und von dieser Methode möchte ich ein Textfeld
beschreiben...
private static StaticMethode() {
//do anything
... write to TextBlock on wpf ...
}
Was ist das für eine statische Methode? Nicht zufällig eine der
Changed-Callbacks eines Dependency- oder AttachedPropertys? Das könnte
man schöner lösen.
Ansonsten könntest du ein Singleton-Objekt bauen, dass
INotifyPropertyChanged implementiert. Auf dieses kannst du das Binding
beziehen und es innerhalb der statischen Methode manipulieren.
XAML (siehe Binding vom Text-Property des TextBlocks):
Hi,
gibt es eine Möglichkeit das ganze in den 2 Way-Mode zu bekommen?
also ich möchte statt nen TextBlock eine TextBox verwenden und in die
TextBox geschriebene Informationen in die Singletone-Class zu
übertragen?
Vielen Dank
Hi,
ich habe das Singleton-Object noch etwas erweitert und möchte es auch
Serialisieren <- damit ich die Daten speichern und laden kann...
das ganze funktioniert aber nicht sooooo gut...
hier mein Singleton:
using (FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write))
11
{
12
ms.WriteTo(file);
13
}
14
}
15
}
16
catch(Exception ex)
17
{
18
MessageBox.Show(ex.Message);
19
}
20
21
}
22
23
private object LoadObject(string fileName)
24
{
25
if (File.Exists(fileName))
26
{
27
try
28
{
29
using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
30
{
31
byte[] bytes = new byte[file.Length];
32
file.Read(bytes, 0, (int)file.Length);
33
34
try
35
{
36
using (MemoryStream ms = new MemoryStream())
37
{
38
BinaryFormatter bf = new BinaryFormatter();
39
ms.Write(bytes, 0, (int)file.Length);
40
ms.Position = 0;
41
42
return bf.Deserialize(ms);
43
}
44
}
45
catch(Exception ex)
46
{
47
MessageBox.Show("MS: " + ex.Message);
48
}
49
}
50
}
51
catch (Exception ex)
52
{
53
MessageBox.Show("Loader: " + ex.Message);
54
}
55
}
56
return null;
57
}
der Fehler hier ist, dass er zwar schon einiges speichert, aber beim
Laden nicht mehr die Felder richtig befüllt (somit befürchte ich, dass
das Speichern schon nicht ganz Korrekt ist)
Hat jemand eine Idee für mich?
Vielen Dank
Hi,
also ich habe nochmal die Felder abgegriffen.
=> vom Prinzip wird alles richtig gespeichert und auch geladen.
=> nur mein INotifyPropertyChanged funktioniert dann nicht mehr.
d.h. weder die Felder in der Oberfläche werden befüllt, noch kann ich
Werte in den Feldern eintragen welche dann Sauber in das Singleton
geladen werden...
LoadObject liefert ja ein neues Objekt vom Typ Singleton. Dieses wird
aber nirgends dem static field "instance" zugewiesen.Brächte aber auch
nichts, da man das static Property "Instance" ja kein PropertyChanged
feuern lassen kann. Das Binding bezöge sich weiterhin auf das
Urpsrungs-Singleton-Objekt.
Ich kenn die Umstände nicht näher, aber ich würde an dieser Stelle eher
versuchen, das alte Singleton-Objekt mit den Daten des neuen Objekts
upzudaten. Also z.B. so:
1
...
2
var deserializedSingleton = (Singleton)LoadObject("dateiname.dat");
3
Singleton.Instance.Update(deserializedSingleton);
4
...
Die Update-Methode könnte so aussehen:
1
private void Update(Singleton newObject)
2
{
3
text = newObject.text; // hier nur Fields zuweisen, keine Properties
Bei PropertyChangedEventArgs mit null oder "" eventuell nochmal
recherchieren. Ich glaub, da gab es eine Empfehlung ab einer bestimmten
.NET-Version...
Hi,
sorry, dass ich erst jetzt zurückschreibe - war unterwegs...
Erstmal "vielen Dank", das funktioniert Großartig!
nun stellt sich aber die Frage, ob ich wirklich ALLE Objekte erneut
auflisten muss, oder ob man das irgendwie Automatisieren kann?
meine Idee war eine schleife, welche alle Objekte vom alten Objekt
durchläuft und mit dem neuen verknüpft (die Objekte können ja [von der
Struktur] niemals unterschiedlich sein).
1
foreach(FieldInfo field in this.GetType().GetFields())
2
{
3
field = newObject.[field.name]
4
5
}
<- aber genau da hat mein Ansatz Lücken.
kann man das Automatisieren?
Vielen Dank
Pack die Daten die Du anzeigen willst in eine eigene Klasse. Spendiere
Deinem Singleton das du als data model misbrauchst ein Property fuer die
Daten, also z.B.:
im xaml passt du den Pfad an (Item.Text statt Text).
Serialisieren/Deserialisieren tust du nun nur die Klasse mit den Daten
und nicht das Singleton. Durch den Setter des Item property werden alle
die auf Item.* binden updated.
NotifyPropertyChanged() zur Vollstaendigkeit:
Danke für die guten und Netten Tipps hier ;)
leider stell ich mich sehr an...
ich habe jetzt das Singleton mal komplett aufgebaut wie von Roger
beschrieben:
> <TextBox Text="{Binding Path=Item.Text, Source={x:Static
local:Singleton.Instance}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
1
public class Singleton : INotifyPropertyChanged
2
{
3
public class Data
4
{
5
public string Text { get; set; }
6
}
7
8
private Data _data = new Data();
9
public Data Item
10
{
11
get => _data;
12
set
13
{
14
_data = value;
15
NotifyPropertyChanged();
16
}
17
}
18
19
public event PropertyChangedEventHandler PropertyChanged;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
23
}
24
25
private Singleton() { }
26
27
private static Singleton instance;
28
public static Singleton Instance { get { return instance ?? (instance = new Singleton()); } }
29
30
}
Das Serialisieren und Deserialisieren habe ich noch nicht implementiert,
soweit bin ich noch nicht
zwar werden die Eingaben sauber erkannt und dem Singleton übergeben,
aber die "Backendseitigen" Eingaben und Änderungen werden nicht ans XAML
übergeben.
=> das TextFeld bleibt leer!
die Markierungen [DataContract] und [DataMember] konnte ich nicht
übergeben, ebenso musste ich aus Data _data; private Data _data = new
Data(); machen, damit überhaupt was ging...
*sorry, für die teils "doofen" Fragen*
Vielen Vielen Dank
Bärnd schrieb:> zwar werden die Eingaben sauber erkannt und dem Singleton übergeben,> aber die "Backendseitigen" Eingaben und Änderungen werden nicht ans XAML> übergeben.
was heisst "Backendseitigen" Eingaben?
Initiale Werte kannst du beim erstellen des Data Object mitgeben, also
1
privateData_data=newData(){Text="Blah"};
und das sollte im GUI erscheinen. Wenn Du die Data properties 'im
Betrieb' veraenderst, dann musst du das dem GUI auch mitteilen ->
INotifyPropertyChanged.
Entweder die Data Klasse implementiert INotifyPropertyChanged, oder wenn
du damit leben kannst dass alle Properties auf einmal refresht werden:
1
publicclassSingleton:INotifyPropertyChanged
2
{
3
/* ... */
4
5
publicvoidModify()
6
{
7
Item.Text="Modified";
8
/* modify some more... */
9
10
NotifyPropertyChanged("Item");
11
}
12
}
> die Markierungen [DataContract] und [DataMember] konnte ich nicht> übergeben,
[DataContract]/[DataMember] sind Attribute von System.ComponentModel,
helfen beim serialisieren/deserialisieren.
> ebenso musste ich aus Data _data; private Data _data = new> Data(); machen, damit überhaupt was ging...
Tschuldigung, es braucht natuerlich ein Objekt damit das ganze laeuft.
> *sorry, für die teils "doofen" Fragen*
Keine Ursache.
Cheers, Roger
Hm, okay
ja,...
ich versteh aber nicht, warum das in meinem Item nicht funktioniert?
1
private Data _data = new Data();
2
public Data Item
3
{
4
get => _data;
5
set
6
{
7
_data = value;
8
NotifyPropertyChanged("Item");
9
}
10
}
11
12
public void Modify(Singleton item, string value)
13
{
14
//Item.Text = "Modified";
15
Item.Text = "as";
16
17
NotifyPropertyChanged("Item");
18
}
wenn ich über mein Main den Aufruf:
> Singleton.Instance.Item.Text = "WertA";
starte, wird dieser in der GUI nicht angezeigt, der Wert aber sauber im
Singleton vorhanden
wenn ich das Modify aufrufe, wird das sauber auch im GUI angezeigt
> Singleton.Instance.Modify();
ich dachte, wenn ich die _data = value setz.. dann ruft er das
NotifyPropertyChanged ebenso mit auf?
=> schließlich will ich viele Aktionen über mein "Hauptprogramm"
aufrufen mit Oberfläche meinte ich die GUI ;)
Serialisieren muss ich dann auch nur
Singleton.Item ? <- dort sind alle meine "Werte"?
beim De-serialisieren, muss ich meine Items updaten, das mach ich über
die beschriebene Load-Methode...
> Entweder die Data Klasse implementiert INotifyPropertyChanged
was ist damit gemeint?
> wenn du damit leben kannst dass alle Properties auf einmal refresht werden
klingt ein Bisschen so, alsob hiermit "größere" nachteile verbunden
wären?
Im Endprodukt sollen mal 15 Textfelder und ein paar Datatables, wenige
Checkboxen und so vorhanden sein... wenn ich jetzt gleichzeitig 30
Felder refresh sollte auch ein Rechner mit unterer Ausstattung das ohne
größerer Latzenz verarbeiten können!?
Bärnd schrieb:> wenn ich über mein Main den Aufruf:>> Singleton.Instance.Item.Text = "WertA";>> starte, wird dieser in der GUI nicht angezeigt, der Wert aber sauber im> Singleton vorhanden
ja, weil eben nur das Text property in Item veraendert wird, und dies
ist ein simples CLR property, es gibt keine notification zum binding.
das funktioniert aber:
weil eben das Item property von Singleton das binding ueber
NotifyPropertyChanged() informiert dass die Werte sich geaendert haben.
(Ein komplett neues Objekt)
> ich dachte, wenn ich die _data = value setz.. dann ruft er das> NotifyPropertyChanged ebenso mit auf?
das
> => schließlich will ich viele Aktionen über mein "Hauptprogramm"> aufrufen mit Oberfläche meinte ich die GUI ;)>> Serialisieren muss ich dann auch nur> Singleton.Item ? <- dort sind alle meine "Werte"?
ja, du deserialiserst ein Data Objekt und dann mittels
1
Singleton.Instance.Item=deserialisiertesObjekt;
machst du das update des GUI.
>>> Entweder die Data Klasse implementiert INotifyPropertyChanged> was ist damit gemeint?
Wenn du willst dass Property-Setter der Data Klasse automatisch die GUI
updaten,
dann muss die Data Klasse das INotifyPropertyChanged interface
implementieren und jeder
setter den PropertyChanged event triggern. Analog dem Singleton.
>> wenn du damit leben kannst dass alle Properties auf einmal refresht werden> klingt ein Bisschen so, alsob hiermit "größere" nachteile verbunden> wären?
Koennte ein Performance Problem sein wenn du Tausende Bindings hast und
nur
eines updaten willst.
> Im Endprodukt sollen mal 15 Textfelder und ein paar Datatables, wenige> Checkboxen und so vorhanden sein... wenn ich jetzt gleichzeitig 30> Felder refresh sollte auch ein Rechner mit unterer Ausstattung das ohne> größerer Latzenz verarbeiten können!?
Ja, ohne Problem.
Cheers, Roger
vielen Dank...
ein kleines Problem existiert noch
zwar kann ich so:
1
Singleton.Instance.Item = new Singleton.Data { Text = "WertA" };
das Feld Text updaten, würde aber das Feld Text2 logischerweise
überschreiben...
gibt es auch eine einfache Möglichkeit "nur ein Feld" zu verändern? Oder
muss ich bei Update von Text auch die alten werte mit übergeben?
man könnte auch hier eine Updatezeile einfügen...
=> die Frage ist, kann man das auch automatisieren? <- z.B. aus der
Klasse heraus? <- leider muss die Klasse aber serialisierbar sein
Bärnd schrieb:> ein kleines Problem existiert noch>> gibt es auch eine einfache Möglichkeit "nur ein Feld" zu verändern? Oder> muss ich bei Update von Text auch die alten werte mit übergeben?
JA, alles oder nichts:
1
Singleton.Instance.Item = new Singleton.Data {
2
Text = "WertA",
3
Text2 = Singleton.Instance.Item.Text2
4
};
Aber da endest du wieder an der Ausgangslage, wo du alle Elemente
aufzaehlen musst die du kopieren willst. Evtl. macht es Sinn das ein
wenig zu Abstrahieren und in der Singleton Klasse anzubieten:
>> leider ohne erfolg...> Weder nur "Text" als auch "Item.Text" funktioniert.
Weil Singleton, welches INotifyPropertyChanged implementiert, eben nur
ein Property Namens 'Item' beherbergt und nicht 'Item.Text' oder 'Text'.
Somit ist das binding auf Item (oder in dem Fall Item.*) nur
angesprochen wenn auch ein notify auf 'Item' erfolgt.
Cheers, Roger
Hi Zusammen...
=> super Thread hier,...
ich habe aber ein kleines Problem! Bei mir ist die Singletone-Class in
einem "Ordner"
Services/Singelton ...
Text="{Binding Path=Item.An, Source={x:Static
local:Services.Singleton.Init}, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
Der Fehler ist "Geschachtelte Typen werden nicht unterstützt"
Lustiger weise funktioniert es trotzdem, aber natürlich will ich den
Fehler nicht haben
=> Muss ich die Singleton ins Main Verzeichnis schieben? oder kann man
das irgendwie trotzdem richtig machen?
Vielen Dank
hani
Der Ordner ist hier wurscht, es geht um den namespace.
Du kannst entweder das Singleton in den Namspace wo
local: hinzeigt 'verschieben' (also namespace definition anpassen).
oder, die bevorzugte Loesung, eine XAML namespace definition fuer den
Services CLR namespace einrichten (analog dem local) und die verwenden.
1
xmlns:services="clr-namespace:[Namespace von local].Services"