I have an listbox, with data inside(nutrition plans) and an mousedoubleclick function that opens an data about certain nutrition plan information(daily nutrition plans) in new page. The GetDailyNutrition class gets the Id from the first listbox.
If I click on "nutrition plan A" on the listbox, it should display the daily nutritions in a different listbox(on the nutritionPlan.xaml view).
The problem is, I could not get to show the daily nutritions in the listbox.
my NutritionPlan.xaml.cs code:
public partial class NutritionPlan : Page
{
private DailyNutritionPlanVM _dailyNutritionplanvm;
public Models.NutritionPlan _NPlan;
public NutritionPlan(Object NPlan)
{
_NPlan = NPlan as Models.NutritionPlan;
InitializeComponent();
}
public void getDailyNutrition()
{
_dailyNutritionplanvm = new DailyNutritionPlanVM();
_dailyNutritionplanvm.LoadData(_NPlan.NutritionPlanId);
DataContext = _dailyNutritionplanvm;
}
}
My NutritionPlan.Xaml code:
<Grid Background="LightBlue">
<ListBox HorizontalAlignment="Left" Height="123" Margin="88,220,0,0" VerticalAlignment="Top" Width="162">
</ListBox>
</Grid>
Listbox where the data is taken:
<ListBox x:Name="NutritionPlansControlListBx" Margin="10,5" Height="282" ItemsSource="{Binding NutritionPlans}"
MouseDoubleClick="ListBox_MouseDoubleClick">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding NutritionPlanName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
MouseDoubleClick class:
private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
_frame.Content = new NutritionPlan(NutritionPlansControlListBx.SelectedItem);
}
First, your view should not know about Model. so I moved the model to view model.
Also you have to be careful with data context since each view only got one. so I changed its type to a container view model type which contains daily plans. At this point your NutritionPlan view starts with one object of NutritionPlanVM.
NutritionPlan.xaml.cs:
public partial class NutritionPlan : Page
{
public NutritionPlanVM ViewModel { get { return DataContext as NutritionPlanVM; } set { DataContext = value; } }
public NutritionPlan(Object NPlan)
{
InitializeComponent();
//ViewModel = new NutritionPlanVM(NPlan);
//or can be ViewModel = a VM selected from RootVM
}
}
This view model needs its LoadData method to be explicitly called in order to create multiple daily plans for itself.
NutritionPlanVM.cs:
public class NutritionPlanVM : DependencyObject
{
Models.NutritionPlan _NPlan;
private ObservableCollection<DailyNutritionPlanVM> _dailyPlans;
public ObservableCollection<DailyNutritionPlanVM> DailyPlans { get { return _dailyPlans; } }
public void LoadData(Models.NutritionPlan _NPlan)
{
var dnpVM = new DailyNutritionPlanVM(_NPlan.NutritionPlanId);
_dailyPlans.Add(dnpVM);
}
}
You need another view model containing an observable collection for all nutrition plans.
public class RootVM : DependencyObject
{
private ObservableCollection<NutritionPlanVM> _nutritionPlans;
public ObservableCollection<NutritionPlanVM> NutritionPlans { get { return _nutritionPlans; } }
//vm data populated in constructor
public RootVM()
{
_nutritionPlans.Add([add all nutrition plans]);
}
}
Now for the binding root, there should be a view corresponding to this RootVM. (e.g., MainWindow). in the constructor of that view you need DataContext = new RootVM()
Now that everything is in place, you can bind to the currently selected item of the first listbox, and use that item to extract view model information:
<ListBox ItemsSource="{Binding ElementName=NutritionPlansControlListBx, Path=SelectedItem.DailyPlans}"/>
Related
I have created a dynamically generated TabControl by binding ItemsSource to MyUnicornsViewModel.
As new items are added to MyUnicornsViewModel... new tab items are created. However, the newly added tabs are not automatically selected in the TabControl.
How can I get new tabs to be selected when they are added?
<TabControl ItemsSource="{Binding MyUnicornsViewModel}" SelectedItem="{Binding SelectedItem}">
<TabControl.ItemTemplate>
<!-- header template -->
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<!-- body template-->
<DataTemplate>
<TextBlock Text="{Binding Content}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
At first, I was hoping there was an event for "ItemsChanged" or "ItemAdded" in the TabControl, that way I can set the SelectedIndex in the code-behind as new items are added.
Another thing I tried was to bind the TabControl.SelectedItem to a SelectedItem property in MyUnicornsViewModel. Sadly, that didn't work either.
MyUnicornsViewModel:
public class MyUnicornsViewModel : ObservableCollection<UnicornViewModel>
{
...
private void AddNewUnicorn()
{
var awesomeUnicorn = new UnicornViewModel();
Add(awesomeUnicorn);
SelectedItem = awesomeUnicorn; //I expected my TabControl to have 'awesomeUnicorn' selected.
}
public UnicornViewModel SelectedItem { get; set; }
}
There are a couple of issues here:
It's very odd to derive a "view model" from ObservableCollection. A view model should contain an observable collection.
View models need to implement the INotifyPropertyChanged interface; it's not clear from the code provide if UnicornViewModel implements this interface, however, MyUnicornsViewModel absolutely does not.
Here's some suggestions:
A view model base class that implements the INotifyPropertyChanged interface will really help get you most of the way. You can write your own using the INotifyPropertyChanged documentation or look for an MVVM framework that fits well with your project (e.g. Prism, MVVM Light, ReactiveUI). Each of these will provide a base class to use for view models - BindableBase, ViewModelBase, ReactiveObject respectively for each of the frameworks above.
MyUnicornsViewModel should have:
An ObservableCollection for the collection of unicorns; this will be bound to the ItemsSource property on your TabControl.
The SelectedItem property must fire the PropertyChanged event when set.
Here's a quick sample using Prism:
public sealed class UnicornViewModel : BindableBase
{
public UnicornViewModel(string name, string content)
{
Name = name;
Content = content;
}
// these properties don't change and therefore don't need to raise property changed
public string Name { get; }
public string Content { get; }
}
public sealed class UnicornsViewModel : BindableBase
{
private UnicornViewModel _selectedUnicorn;
public UnicornsViewModel()
{
AddUnicornCommand = new DelegateCommand(AddUnicorn);
ClearUnicornsCommand = new DelegateCommand(ClearUnicorns, () => HasUnicorns).ObservesProperty(() => HasUnicorns);
}
public ObservableCollection<UnicornViewModel> Unicorns { get; } = new ObservableCollection<UnicornViewModel>();
public UnicornViewModel SelectedUnicorn
{
get => _selectedUnicorn;
set => SetProperty(ref _selectedUnicorn, value, () => RaisePropertyChanged(nameof(HasUnicorns)));
}
public DelegateCommand AddUnicornCommand { get; }
public DelegateCommand ClearUnicornsCommand { get; }
private bool HasUnicorns => Unicorns.Any(); // helper property for the clear command's can execute
private void AddUnicorn()
{
Unicorns.Add(new UnicornViewModel($"Unicorn {Unicorns.Count + 1}", Guid.NewGuid().ToString()));
SelectedUnicorn = Unicorns.Last();
}
private void ClearUnicorns()
{
SelectedUnicorn = null;
Unicorns.Clear();
}
}
So I just setup a project and added a custom UserControl that looks like this.
<Grid>
<ItemsControl ItemsSource="{Binding UserViewModel.Users}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<controls:UserCard/>
<TextBlock Text="{Binding Name}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
As you can see I tried binding the Text property buti it doesn't bind.
Now there could be a lot of reasons to why it's behaving like this so I will try to narrow it down.
I've created a BaseViewModel that will hold my ViewModels and it looks like this.
public class BaseViewModel : ObservableObject
{
public UserViewModel UserViewModel { get; set; } = new UserViewModel();
}
And then I've setup my ViewModel like this
public class UserViewModel : ObservableObject
{
public ObservableCollection<User> Users { get; set; } = new ObservableCollection<User>();
public UserViewModel()
{
Users.Add(new User{Name = "Riley"});
Users.Add(new User{Name = "Riley1"});
}
}
Simple, now I do have a ObservableObject that looks like this and deals with the INPC
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
And in my MainView.xaml
I've set the DataContext like so
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new BaseViewModel();
}
}
It's the exact same for the UserControl
And this is where I actually add the UserControl so it displays in the MainWindow
<ItemsControl ItemsSource="{Binding UserViewModel.Users}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<controls:UserCard/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Now the issue is that it doesn't bind the Data, I want to display the Name property from the Model but it's not displaying it and I am not sure why, if I try to bind it to a TextBlock property in the MainView directly it works fine.
I am unsure to why it's behaving like this and I would like to understand why.
Do I need to make use of DependencyProperties? Or is it just a case of me creating a new instance of the BaseViewModel? Where did I go wrong?
Your MainViewWindow contains an ItemsControl with the binding ItemsSource="{Binding UserViewModel.Users}", with each item being displayed with a <controls:UserCard/>. But your user control is then trying to bind to the list again with "{Binding UserViewModel.Users}". Why are you trying to display a list inside another list?
I suspect the problem here is that you think your custom UserControl's DataContext is still pointing to the BaseViewModel, like its parent. It isn't. The DataContext of each item in an ItemsControl points to it's own associated element in the list, i.e. an instance of type User.
UPDATED: Let's say you have a main view model with a list of child view models, like this:
public class MainViewModel : ViewModelBase
{
public MyChildViewModel[] MyItems { get; } =
{
new MyChildViewModel{MyCustomText = "Tom" },
new MyChildViewModel{MyCustomText = "Dick" },
new MyChildViewModel{MyCustomText = "Harry" }
};
}
public class MyChildViewModel
{
public string MyCustomText { get; set; }
}
And let's say you set your MainWindow's DataContext to an instance of MainViewModel and add a ListView:
<ListView ItemsSource="{Binding MyItems}" />
If you do this you'll see the following:
What's happening here is that the ListView is creating a container (of type ContentPresenter) for each of the three elements in the list, and setting each one's DataContext to point to its own instance of MyChildViewModel. By default ContentPresenter just calls 'ToString()' on its DataContext, so you're just seeing the name of the class it's pointing to. If you add a ToString() operator to your MyChildViewModel like this:
public override string ToString()
{
return $"MyChildViewModel: {this.MyCustomText}";
}
... then you'll see that displayed instead:
You can also override the ListViewItem's template entirely, and since it already points to its associated instance of MyChildViewModel you can just bind directly to its properties:
<ListView ItemsSource="{Binding MyItems}">
<ListView.ItemTemplate>
<DataTemplate>
<!-- One of these gets created for each element in the list -->
<Border BorderBrush="Black" BorderThickness="1" Background="CornflowerBlue" CornerRadius="5" Padding="5">
<TextBlock Text="{Binding MyCustomText}" Foreground="Yellow" />
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Which will change the display to this:
Make sense?
I have the below problem: I have two different user controls inside a parent user control. These are trainList, which holds a list of train objects and trainView, which is an user control that shows details of the selected train in the list.
My wish is to share a variable of trainList with trainView.
What I have now is:
Parent user control:
<UserControl>
<UserControl>
<customControls:trainList x:Name="trainList"></customControls:trainList>
</UserControl>
<UserControl>
<customControls:trainView x:Name="trainView"></customControls:trainView>
</UserControl>
<TextBlock DataContext="{Binding ElementName=trainList, Path=SelectedTrain}" Text="{ Binding SelectedTrain.Id }">Test text</TextBlock>
</UserControl>
TrainList class:
public partial class TrainList : UserControl
{
public TrainList()
{
this.InitializeComponent();
this.DataContext = this;
}
public Train SelectedTrain { get; set; }
public void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.Print(this.SelectedTrain.Id);
}
}
Note: The Train class implements INotifyPropertyChanged.
If I got this to work, I'd apply the binding to the trainView user control (not sure if this would work) instead to the text block.
<UserControl>
<customControls:trainView x:Name="trainView" DataContext="{Binding ElementName=trainList, Path=SelectedTrain}"></customControls:trainView>
</UserControl>
And then, I would access that variable someway from the code-behind of trainView.
(And after this, I would like to share a different variable from trainView with its parent user control, but maybe that's another question).
My current question is: could this be done this way or would I need to follow another strategy?
Take this simple view model, with a base class that implements the INotifyPropertyChanged interface, and a Train, TrainViewModel and MainViewModel class.
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void SetValue<T>(
ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (!Equals(storage, value))
{
storage = value;
OnPropertyChanged(propertyName);
}
}
}
public class Train : ViewModelBase
{
private string name;
public string Name
{
get { return name; }
set { SetValue(ref name, value); }
}
private string details;
public string Details
{
get { return details; }
set { SetValue(ref details, value); }
}
// more properties
}
public class TrainViewModel : ViewModelBase
{
public ObservableCollection<Train> Trains { get; }
= new ObservableCollection<Train>();
private Train selectedTrain;
public Train SelectedTrain
{
get { return selectedTrain; }
set { SetValue(ref selectedTrain, value); }
}
}
public class MainViewModel
{
public TrainViewModel TrainViewModel { get; } = new TrainViewModel();
}
which may be initialized in the MainWindow's constructor like this:
public MainWindow()
{
InitializeComponent();
var vm = new MainViewModel();
DataContext = vm;
vm.TrainViewModel.Trains.Add(new Train
{
Name = "Train 1",
Details = "Details of Train 1"
});
vm.TrainViewModel.Trains.Add(new Train
{
Name = "Train 2",
Details = "Details of Train 2"
});
}
The TrainDetails controls would look like this, of course with more elements for more properties of the Train class:
<UserControl ...>
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Details}"/>
</StackPanel>
</UserControl>
and the parent UserControl like this, where I directly use a ListBox instead of a TrainList control:
<UserControl ...>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding Trains}"
SelectedItem="{Binding SelectedTrain}"
DisplayMemberPath="Name"/>
<local:TrainDetailsControl Grid.Column="1" DataContext="{Binding SelectedTrain}"/>
</Grid>
</UserControl>
It would be instantiated in the MainWindow like this:
<Grid>
<local:TrainControl DataContext="{Binding TrainViewModel}"/>
</Grid>
Note that in this simple example the elements in the UserControls' XAML bind directly to a view model instance that is passed via their DataContext. This means that the UserControl know the view model (or at least their properties). A more general approach is to declare dependency properties in the UserControl class, that are bound to view model properties. The UserControl would then be independent of any particular view model.
So I am trying to bind the following ViewModel:
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<ListBoxItem> _PlacesOrCities;
public ObservableCollection<ListBoxItem> PlacesOrCities
{
get { return _PlacesOrCities; }
set { _PlacesOrCities = value; RaisePropertyChanged("PlacesOrCities"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ViewModel()
{
_PlacesOrCities = new ObservableCollection<ListBoxItem>();
}
}
To the following xaml:
<ListBox Name="lbPlacesCity" ItemsSource="{Binding Path=(gms:MainWindow.ViewModel).PlacesOrCities, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate DataType="models:ListBoxItem">
<TextBlock Style="{StaticResource MaterialDesignBody2TextBlock}" Text="{Binding Name}" Visibility="{Binding Visibility}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In the codebehind as such:
public ViewModel ViewModel { get; set; }
public MainWindow()
{
InitializeComponent();
ViewModel = new ViewModel();
DataContext = ViewModel;
}
And upon firing a button click event- I try to set the values of the observable collection using a in memory list:
private void StateProvince_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
_CurrentSelectionPlaces = Canada.Provinces
.FirstOrDefault(x => x.Abbreviation == _SelectedStateProvince_ShortName)
.Place.OrderBy(x => x.Name).ToList();
foreach (var currentSelectionPlace in _CurrentSelectionPlaces)
{
ViewModel.PlacesOrCities.Add(currentSelectionPlace);
}
}
But it seems like none of the items are being added to the collection. Am I binding it incorrectly?
I've tried quite a few solutions but none of them seem to change the result- where no items in the list are being loaded into the collection properly.
EDIT:
It may be worth noting that the ListBoxItem as seen in the ViewModel is a custom model:
public class ListBoxItem
{
[J("Name")] public string Name { get; set; }
[J("PostalCodes")] public string[] PostalCodes { get; set; }
public Visibility Visibility { get; set; } = Visibility.Visible;
}
You should try to fit to the MVVM pattern, so the population of the list should occur at viewmodel level and not in the view's code behind.
You mentioned that you use a click event, instead of doing so, try to bind the command property of the button to a command in the viewmodel, see this link with an explanation of several types of commands and how to use them: https://msdn.microsoft.com/en-us/magazine/dn237302.aspx
In the other hand, if you already set the data context in the window constructor, to bind the ListBox items source you only need the name of the property to bind, "PlacesOrCities":
<ListBox Name="lbPlacesCity" ItemsSource="{Binding Path=PlacesOrCities, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate DataType="models:ListBoxItem">
<TextBlock Style="{StaticResource MaterialDesignBody2TextBlock}" Text="{Binding Name}" Visibility="{Binding Visibility}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
It would also be recommendable trying to load the items in the list without any template, you can use ListBox DisplayMemberPath property to display the name, and once you are able to load items, apply the style.
Also in the way you use ObservableCollection, you actually need to replace the whole collection instead of adding to fire RaisePropertyChanged, try a normal property instead.
public ObservableCollection<ListBoxItem> PlacesOrCities {get;set;} = new ObservableCollection<ListBoxItem>();
Modifying the collection will update the UI, so whenever you use Add or Clear, the UI should know it.
Hope it helps.
I am populating an ItemsControl with various elements, including Buttons and ComboBox elements. Accessing and populating the elements is simple, but I'm stuck on how to detect and associate which Item in the ItemsControl the ComboBox (or Button) belongs to.
To help illustrate the problem, consider the following basic UI:
Now, when I use the ComboBox or Button I want to be able to associate that use only with the ItemControl Item it's a part of. However, currently, if I select an item in the ComboBox every ComboBox in the ItemsControl will reflect that change.
I can capture the SelectedItem in the below ListBox, but ideally, I would like to be able to display both the SelectedItem and which ItemControl Item it came from. For instance, ComboBoxItem1, My First Property - From Item (1).
I am strictly adhering to MVVM principals, and consequently, I am not looking for any solutions using code-behind.
TL;DR
I know the code can become unwieldy. I believe the above description is adequate to state my problem, but I am including the basic boiler plate code below in case it's helpful in posting an answer. (Obviously, I have implemented INotifyProperty and ICommand elsewhere):
MainWindowView.xaml
<ItemsControl Width="300" Height="200" ItemsSource="{Binding MyObservableCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="2" Margin="10">
<StackPanel Margin="0,10,0,10">
<TextBlock Margin="10,0,0,0" Text="{Binding MyProperty}" FontWeight="Bold"/>
<ComboBox Width="270" Text="myBox" ItemsSource="{Binding DataContext.ComboOptions, RelativeSource={RelativeSource AncestorType=ItemsControl}}" DisplayMemberPath="ListItem" SelectedItem="{Binding DataContext.SelectedItem, RelativeSource={RelativeSource AncestorType=Window}}"/>
<RadioButton Width ="270" Content="Button1" Command="{Binding DataContext.GetButtonCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" CommandParameter="Button1" Style="{DynamicResource {x:Type ToggleButton}}"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
MyComboBoxOptionsViewModel.cs
public class MyComboBoxOptionsViewModel : ObservableObject
{
private MyComboBoxOptionsModel _myComboBoxOptions = new MyComboBoxOptionsModel();
public MyComboBoxOptionsViewModel(MyComboBoxOptionsModel _myComboBoxOptions)
{
this._myComboBoxOptions = _myComboBoxOptions;
}
public string ComboBoxOption
{
get { return _myComboBoxOptions.ComboBoxOption; }
set
{
_myComboBoxOptions.ComboBoxOption = value;
RaisePropertyChangedEvent("ComboBoxOption");
}
}
}
MyComboBoxOptionsModel.cs
public class MyComboBoxOptionsModel
{
public string ComboBoxOption { get; set; }
}
MainWindowViewModel.cs
public class MainWindowViewModel : ObservableObject
{
private ObservableCollection<string> _messages = new ObservableCollection<string>();
private ObservableCollection<MyViewModel> _myObservableCollection = new ObservableCollection<MyViewModel>();
private List<MyComboBoxOptionsViewModel> _comboOptions = new List<MyComboBoxOptionsViewModel>();
private MyComboBoxOptionsViewModel _selectedItem = new MyComboBoxOptionsViewModel(null);
public MainWindowViewModel()
{
_myObservableCollection.Add(new MyViewModel(new MyModel { MyProperty = "My First Property" }));
_myObservableCollection.Add(new MyViewModel(new MyModel { MyProperty = "My Second Property" }));
_comboOptions.Add(new MyComboBoxOptionsViewModel(new MyComboBoxOptionsModel { ComboBoxOption = "Option1" }));
_comboOptions.Add(new MyComboBoxOptionsViewModel(new MyComboBoxOptionsModel { ComboBoxOption = "Option2" }));
_comboOptions.Add(new MyComboBoxOptionsViewModel(new MyComboBoxOptionsModel { ComboBoxOption = "Option3" }));
}
public MyComboBoxOptionsViewModel SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
_messages.Add(_selectedItem.ComboBoxOption);
RaisePropertyChangedEvent("SelectedItem");
}
}
public List<MyComboBoxOptionsViewModel> ComboOptions
{
get { return _comboOptions; }
set
{
if (value != _comboOptions)
{
_comboOptions = value;
RaisePropertyChangedEvent("ComboOptions");
}
}
}
public ObservableCollection<MyViewModel> MyObservableCollection
{
get { return _myObservableCollection; }
set
{
if (value != _myObservableCollection)
{
_myObservableCollection = value;
RaisePropertyChangedEvent("MyObservableCollection");
}
}
}
public ObservableCollection<string> Messages
{
get { return _messages; }
set
{
if (value != _messages)
{
_messages = value;
RaisePropertyChangedEvent("Messages");
}
}
}
}
I'm looking at the UI you want and think you basically need a main view model with a collection of item view models.
In that item view model create a command and a selected item property you can bind in your template to the combo box and button. That gives you a strict mvvm binding to a single instance of the combo box value and a command which is executed by the single instance of the button.
Your bindings for combo box items will then need an explicit source as part of the binding so you can hook into one collection of values from the main view model. Or add a collection to your item view model and keep it all nice a clean and together.
As you mention, you're code is very detailed - which is great - but I may have missed some other meaning from it.
Apologies if this is an answer to the wrong question :)