[WPF] RadioButton Context an ViewModel Property binden.
-
Morgen Leute,
folgendes liegt vor:
View:
<Grid> <HeaderedItemsControl ItemsSource="{Binding Tools}" Header="Toolbox" Foreground="White" > <HeaderedItemsControl.ItemTemplate> <DataTemplate> <RadioButton GroupName="Tools" Template="{StaticResource RadioButtonTemplate}" /> </DataTemplate> </HeaderedItemsControl.ItemTemplate> </HeaderedItemsControl> </Grid>
ViewModel:
public class ToolBoxViewModel : WorkspaceViewModel { public ObservableCollection<Tool> Tools { get; private set; } public Tool _selectedItem; public Tool SelectedItem { get { return this._selectedItem; } set { if (this._selectedItem != value) { this._selectedItem = value; this.NotifyPropertyChanged("SelectedItem"); } } } public ToolBoxViewModel() { this.Tools = this.CreateToolBoxElements(); } private ObservableCollection<Tool> CreateToolBoxElements() { return new ObservableCollection<Tool>() { new Tool("/Images/Properties.png") { DisplayName = "CheckBox" }, new Tool("") {DisplayName = "Button"}}; } }
Wie krieg ich es denn jetzt hin das aktuelle Checked Item an mein SelectedItem zu binden? Habs schon mit nem Command versucht, bzw mit nem ListItem drumherum aber alles erfolglos. Habt ihr einen Tipp?
-
Erstell ein ViewModel für die
Tool
Elemente und mach dort einIsSelected
Property rein. Die Verlinkung machst du dann hinten über die ViewModels. Wenn sich also einIsSelected
beimToolViewModel
auftrue
ändert, wird dasIsSelected
des bisherigen selektiertenToolViewModel
auffalse
gesetzt und dasSelectedItem
desToolBoxViewModel
aktualisiert. Am besten kann dies wahrscheinlich gleich dasToolBoxViewModel
machen. Also braucht jedesToolViewModel
eine Referenz auf das dazugehörigeToolBoxViewModel
.Grüssli
-
Hmm das wäre ne Idee. Aber ich hab gerade gesehen das ich vergessen hab einen Wichtigen Fakt mit zur erläutern: Ich selektiere die RadioButtons in der View mit der Mouse und möchte das an das ViewModel propagieren, ich glaub dann funktioniert das mit deiner Lösung nicht mehr oder?
-
Ich seh das Problem nicht ganz. Du selektierst die
RadioButton
mit der Maus, dadurch verändert sich ja dieChecked
Property. Wenn du nun dieChecked
Property an dieIsSelected
Property desToolViewModel
bindest, sollte dies doch kein Problem machen. Oder verstehe ich dich falsch?Grüssli
-
Ja klar, hast Recht, ich werds mal probieren, danke.
-
Schau mal Dravere, wie gefällt dir die Lösung:
ToolBoxViewModel
private ObservableCollection<ToolViewModel> CreateToolBoxElements() { Tool t = new Tool("/Images/Properties.png") {DisplayName = "CheckBox" }; ToolViewModel tv = new ToolViewModel(t); tv.SelectionChanged += this.OnSelectionChanged; return new ObservableCollection<ToolViewModel>() { tv }; } private void OnSelectionChanged(object sender, ToolSelectionChangedEventArgs e) { this.SelectedItem = e.ChangedTool; }
ToolViewModel:
public class ToolViewModel : ObservableObject { private bool isSelected; public bool IsSelected { get { return this.isSelected; } set { if (this.isSelected != value) { this.isSelected = value; this.NotifyPropertyChanged("IsSelected"); this.OnSelectionChanged(); } } } public Tool Tool { get;private set; } public event EventHandler<ToolSelectionChangedEventArgs> SelectionChanged; public ToolViewModel(Tool t) { this.Tool = t; this.IsSelected = false; } private void OnSelectionChanged() { EventHandler<ToolSelectionChangedEventArgs> h = this.SelectionChanged; if (h != null) h(this, new ToolSelectionChangedEventArgs() { ChangedTool = this.Tool}); } }
Dann brauch ich die nich bei jedem ToolViewModel die Referenz auf die ToolBoxViewModel mitschleppen.
Natürlich ist das dann am RadioButton Two-Way gebindet.
-
Firefighter schrieb:
Schau mal Dravere, wie gefällt dir die Lösung
Mir gefallen daran nicht:
1. Man muss viel mehr schreiben!
->ToolSelectionChangedEventArgs
Klasse
-> Entsprechender Code, welcher aufSelectionChanged
reagiert.
2. Die Sache ist fehleranfälliger!
-> Du musst die Event-Handler entfernen, wenn einToolViewModel
entfernt wird!Wenn du direkt eine Referenz behalten würdest, könntest du das folgende machen:
class ToolViewModel { // ... private bool isSelected; private ToolBoxViewModel parent; // ... public bool IsSelected { get { return this.isSelected; } set { if(this.isSelected != value) { this.isSelected = value; this.parent.SelectedItem = this; // ... notify blabla } } } }
SelectedItem
hast du ja bereits inToolBoxViewModel
. Dort musst du nur noch das folgende ergänzen:public ToolViewModel selectedItem; public ToolViewModel SelectedItem { get { return this._selectedItem; } set { if (this._selectedItem != value) { if(this._selectedItem != null) { this._selectedItem.IsSelected = false; } this._selectedItem = value; if(this._selectedItem != null) { this._selectedItem.IsSelected = true; } this.NotifyPropertyChanged("SelectedItem"); } } }
Und übrigens:
private void OnSelectionChanged() { EventHandler<ToolSelectionChangedEventArgs> h = this.SelectionChanged; if (h != null) h(this, new ToolSelectionChangedEventArgs() { ChangedTool = this.Tool}); }
->
private void OnSelectionChanged() { var h = this.SelectionChanged; //^^^ if (h != null) h(this, new ToolSelectionChangedEventArgs() { ChangedTool = this.Tool}); // und wäre ein vernünftiger Konstruktur hier nicht klüger? }
Aber ich weiss nicht, kommt natürlich auch auf die Umgebung an. Ob du dabei bleiben willst, dass
SelectedItem
dasTool
zurückgibt und nicht dasToolViewModel
.
Wieso willst du aber hier überhaupt Events verwenden? Klar ist Entkopplung sinnvoll, aber ist sie hier auch wirklich nötig? Eine niedrige Kopplung bedeutet meistens auch eine erhöhte Komplexität.Grüssli
-
Erdrückende Beweisführung
Und ich dachte meine Events wären was tolles, da hab ich natürlich voll vergessen das ich die Entfernen muss. Ich Dösbattel.
Dann ist deine Lösung natürlich besser. Klare Sache.
Du und dein var. Das kriegen wir vermutlich nich mehr raus wa ;):p