Reputation: 19844
I'm experimenting with MVVM and I can't quite wrap my mind around it.
I have a View (windows) that has several repeated controls.
Let's say I have 4 textbox - button pairs. Their behavior should be the same, after pressing a button paired textbox says "Hello World!"
I have tried several options I could think of:
Is there any other way? I suspect DataTemplates could be of use, but I'm not sure how.
Upvotes: 2
Views: 121
Reputation: 24453
There's no need to create a separate ViewModel for a reusable control that has such simple behavior. Just by adding a few DependencyProperties and an event handler to the simple UserControl you can reuse the logic and only set the properties that are actually different on each instance. For the UserControl XAML you just need to hook up the TextBox to the DependencyProperty and the Button to a Click handler.
<DockPanel>
<Button Content="Reset" Click="Button_Click"/>
<TextBox Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Text}"/>
</DockPanel>
The code for the UserControl just needs to define the properties that can be bound externally and the handler to reset the Text.
public partial class ResetTextBox : UserControl
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(ResetTextBox),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty ResetTextProperty = DependencyProperty.Register(
"ResetText",
typeof(string),
typeof(ResetTextBox),
new UIPropertyMetadata(String.Empty));
public string ResetText
{
get { return (string)GetValue(ResetTextProperty); }
set { SetValue(ResetTextProperty, value); }
}
public ResetTextBox()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Text = ResetText;
}
}
Then to use the control you just need to bind to your ViewModel string properties and set the default text that should be applied on a reset which can either be hardcoded here, or bound to other VM properties.
<StackPanel>
<local:ResetTextBox ResetText="One" Text="{Binding Name1}"/>
<local:ResetTextBox ResetText="Two" Text="{Binding Name2}"/>
<local:ResetTextBox ResetText="Three" Text="{Binding Name3}"/>
</StackPanel>
Upvotes: 1
Reputation: 42003
What you describe is such an abstract and contrived idea that it doesn't warrant MVVM. You're talking about TextBox
es and Buttons
, which are all 'View', and not the MVVM way of thinking. You'd almost always start with a Model.
There is no 'Model' per-se here though; your specification is literally to set the value of a TextBox
on a Button
click. The seemingly random list of '4' items (picked out of nowhere) and a seemingly useless TextBox
mean nothing.
Putting that aside and assuming that you have a set of 4 business entities, each with a field on them that is user-editable, and an action that the user can trigger, you'd do this:
MyItemModel
AllMyItemsListModel
Then for the View:
ItemsControl
, with ItemsSource
bound to an instance of the 'collection' of the second ViewModel classItemTemplate
, have a template or UserControl
for each itemUserControl
, bind the TextBox
's Text property to the appropriate property of the first classButton
's Command
property to a property on the first class returning an ICommand
- using RelayCommand
for exampleI don't know what you mean about 'extracting texts from nested ViewModels to the window ViewModel' - what does that mean and why would you want to do it?
Hope that helps.
Upvotes: 2
Reputation: 3916
Number 3. Except there would just be one UserControl with viewmodel and then the Main page that would have multiple instances of that UserControl on it. If the main window needs info from the UserControl you could pass it through events or use something like MVVM Light and it's messenger class.
Upvotes: 1