|
|
Die Labels benötigen eine Eigenschaft, die PB benötigen 3. Also 15 Eigenschaften deklarieren ... zB pb_Statusanzeige_MaximumEs ist auch nicht interessant, ob sich die Property auf ein Control bezieht oder nicht. MVVM versucht gerade, diese Trennung möglichst so hinzubekommen.
Das es aber nun ProgessBars sind, zeigt mir die Entwicklungsumgebung beim Tippen von 'pb' mindestens 12 Einträge. pb_Statusanzeige_Maximum = 100 ist für mich persönlich auch nicht so lesbar (bzw weiss man nicht sofort, dass sich dieser Wert auf ein Controll bezieht oder eine einfache blöde Variabel ist).
Ich möchte das es zB so aussieht pb_Statusanzeige.Maximum = 100. Die Vorschläge im Editor (intel...weiss jetzt nicht, wie das heisst :-() reduzieren sich auf die 4 pb's, und nach dem Punkt hab ich dann eben die Eigenschaften, die Verändert werden können ..
// INotifyPropertyChanged.PropertyChanged Event auslösen habe ich hier ausgelassen
public class ProgressViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Maximum {get;set;}
public int Minimum {get;set;}
public int Value {get;set;}
}
// INotifyPropertyChanged.PropertyChanged Event auslösen habe ich hier ausgelassen
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
Progress1 = new ProgressViewModel();
Progress2 = new ProgressViewModel();
Progress3 = new ProgressViewModel();
// ...
}
public event PropertyChangedEventHandler PropertyChanged;
public ProgressViewModel Progress1 { get; private set; } // setter nicht vergessen!!
public ProgressViewModel Progress2 { get; private set; }
public ProgressViewModel Progress3 { get; private set; }
public string Text1 { get; set; }
public string Text2 { get; set; }
private void ExampleAccess()
{
Progress1.Maximum = 100; // mit '.' und Intellisense
}
}
<StackPanel>
<ProgressBar Maximum="{Binding Progress1.Maximum}"
Minimum="{Binding Progress1.Minimum}"
Value="{Binding Progress1.Value}"/>
<!-- usw... -->
</StackPanel>
.. Wie bei Forms ebenDiese Haltung musst Du ablegen. Du machst jetzt WPF.
|
|
|
Ähem, sollte eigentlich ein Edit meiner Antwort werden. Sorry.
– ffordermaier 17.08.2012
|
||
|
+1 Geht schon in Ordnung. Und schön auf den Punkt gebracht. Eigentlich waren es ja zwei Fragen:
"Wie mache ich dynamische Properties?" und "Wie löse ich das eigentliche Problem?" Da haben zwei Antworten auf jeden Fall ihre Daseinsberechtigung. – Matthias Hlawatsch 17.08.2012
|
|
|
|
+1, coole Idee. Mit nem TypeDescriptor hab ich seit WinForms nicht mehr rumgetrickst, ist aber ein plausibler Ansatz. Für die WPF Infrastruktur sicher verständlich, aber im eigenen nutzenden Code damit hantieren zu müssen, stell ich mir irgendwie eklig vor...
– ffordermaier 16.08.2012
|
||
|
+1 Ja, so könnte es gehen. Der Vollständigkeit halber, und umzu verhindern, dass der letzte Satz des Artikels überlesen wird, hier noch der Link zum zweiten Teil: http://msdn.microsoft.com/en-us/magazine/cc163804.aspx
– Matthias Hlawatsch 17.08.2012
|
dynamic myDynPropertyHost = new MyDynamicObject();
myDynPropertyHost.SomeProperty = 123;
|
|
|
Dem letzten Satz schließe ich mich an: wäre interessant zu wissen, was Du mit diesen Properties eigentlich anstellen willst - insbesondere, wie Dir die Möglichkeit, dynamisch Properties zu ergänzen, den Umstieg von Windows Forms zu WPF erleichtert.
– Matthias Hlawatsch 17.08.2012
|
Wenn Du Dein Vorhaben etwas genauer spezifizieren kannst, findet sich vielleicht noch eine andere (mit hoher Wahrscheinlichkeit einfachere) Lösung.
<Label Content="{Binding label_anzeige_Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="45" HorizontalAlignment="Left" Margin="92,84,0,0" Name="label_anzeige" VerticalAlignment="Top" Width="209" />public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var view = new mvvm();
DataContext = view;
}
}
class mvvm :PForms
{
public mvvm()
{
label_anzeige = pLabel("label_anzeige"); // <-- die wichtige Zeile für das Pseudolabel. Als Übergabewert den Namen des Labels in der UI
Timer t = new Timer(2000);
t.Elapsed += new ElapsedEventHandler(t_Elapsed);
t.Start();
}
void t_Elapsed(object sender, ElapsedEventArgs e)
{
Timer t = (Timer)sender;
t.Stop();
label_anzeige.Content = "test";
}
}
public class PForms : INotifyPropertyChanged
{
public PLabel pLabel(string Name)
{
var lb = new PLabel(Name);
PropertyInfo[] pi = lb.GetType().GetProperties();
foreach (PropertyInfo propertyInfo in lb.GetType().GetProperties())
{
// Und hier müsste nun für jede Eigenschaft in PLabel ein Properts in Form von Name + _ + Eigenschaftsname erzeugt werden
}
lb.PropertyChanged += new PLabel.PropertyChangedEvent(P_PropertyChanged);
return lb;
}
void P_PropertyChanged(string Propertyname, object Value)
{
try
{
PropertyInfo pi = this.GetType().GetProperty(Propertyname);
pi.SetValue(this, Value, null);
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(Propertyname));
}
catch
{ }
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class PLabel
{
public delegate void PropertyChangedEvent(string PropertyName, object Value);
public event PropertyChangedEvent PropertyChanged;
public String Name { get; set; }
public PLabel(string name)
{
Name = name;
}
private string _content;
public string Content
{
get { return _content; }
set
{
_content = value;
PropertyChanged(Name + "_Content", Content);
}
}
}
|
|
| 1 |
Danke für den ausführlichen Blick hinter die Kulissen.
Ich hab's vielleicht noch nicht ganz verstanden, aber mein Bauchgefühl sagt: don't fight the framework. Die vielen Properties, die Dich nerven, entstehen in der ViewModel-Klasse? Hast Du schon mal überlegt, ob Dir die Index-Syntax beim Binding helfen könnte? (Binding=MyDict[MaxStatus]...) Siehe z.B. http://msdn.microsoft.com/de-de/library/system.windows.data.binding.path.aspx – Matthias Hlawatsch 17.08.2012
|
// INotifyPropertyChanged.PropertyChanged Event auslösen habe ich hier ausgelassenpublic
class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ProgressViewModel Progress1 { get; }
public ProgressViewModel Progress2 { get; }
public ProgressViewModel Progress3 { get; }
public string Text1 { get; set; }
public string Text2 { get; set; }
private void ExampleAccess()
{
ProgressBar1.Maximum = 100; // mit '.' und Intellisense
}
}
|
|
|
Muss auch
Progress1.Maximum heißen. Du beziehst Dich ja damit auf die Property MainViewModel.Progress1 Sorry, war wohl ein Tippfehler. Habs in meinem Post editiert. – ffordermaier 17.08.2012
|
||
|
Achja, und im Konstruktor des MainViewModels solltest Du die Properties auch initialisieren. Hab meinen Post nochmal angepasst.
– ffordermaier 17.08.2012
|
||
|
Das initialieren im Konstruktor hatte ich auch schon versucht. Hatte dann aber noch einen kleinen Fehler, so das die Anzeige sich nicht aktuallisierte. Einen starken Espresso später klappte es.
Mein Ansatz, den ich aus deinem ersten Post versucht hab, klappt auch schon (zumindest in eine Richtung). Die Handhabung, wie man nun die Eigenschaften anspricht, ist gleich. – Brainy 17.08.2012
|
||
|
Der Aufwand ist auch relativ gleich ... mal übers WE drüber nachdenken, was für Vorteile sich ergeben.
Vielen lieben dank für die Hilfe – Brainy 17.08.2012
|
||
|
Gern geschehen. Wenn Dich nach dem Wochenende des Grübelns das Gefühl beschleichen sollte, dass meine Antwort Dein Problem hinreichend gelöst hat, würde ich mich freuen, wenn Du sie durch Klicken des grünen Häkchens als "akzeptiert" kennzeichnest.
– ffordermaier 17.08.2012
|
||
|
Deine Lösung ist so genial einfach , da kann man nur das grüne Häckchen drücken.
Wobei ich meine Lösung auch nicht soooooo schlecht schlecht finde. Vodoo ist sie auf keinen Fall .. werde meinen Ansatz vielleicht noch ein wenig weiter denken und evtl hier vorstellen – Brainy 17.08.2012
|
||
|
Danke :-) Voodoo hin oder her, "Keep it simple" ist nie schlecht. Bin schon gespannt auf Deine Lösung...
– ffordermaier 17.08.2012
|
||
|
Hi, ich hab meine Lösung nicht weiter verfolgt. Deine Lösung brachte mir genau das, was ich haben wollte. Vielmehr hat mich beschäftigt, wieso ich nicht drauf gekommen bin. Ich wusste einfach nicht, dass es mit der Bindung "pb.Content" (also dieser Punkt) funktioniert. So bekomm ich mein 'Feel like Forms' hin und verstoss in keinem Punkt dem MVVM. Also nochmal Danke
– Brainy 20.08.2012
|