I am following MVVM Pattern and I want to bind ListView ItemsSource using XAML, not in even
this.Datacontext = ObservableCollection property.
My code is like this:
<ListView x:Name="MenuBarList"
Grid.Row="2"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Path=Menu.Option}"
Width="{Binding MainMenuWidth}"
SelectedItem="{Binding Path=SelectedMainMenuOption, Mode=TwoWay}" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" TextWrapping="Wrap" IsHitTestVisible="False" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and the Menu is the property and it will seat on the ViewModel. Option is the Class of the Property, so I am using Menu.Option
My Menu is the property of ContentMenuModel type and ContentMenuModel is the class which contain the property of Option and Title and Image.
See the property of the Menu which is inside of the ViewModel
public const string MenuPropertyName = "Menu";
private ContentMenuModel _Menu = null;
/// <summary>
/// Gets the Menu collection.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ContentMenuModel Menu
{
get
{
return _Menu;
}
set
{
if (_Menu == value)
return;
_Menu = value;
// Update bindings, no broadcast
RaisePropertyChanged(MenuPropertyName);
}
}
And the ContentMenuModel class looks like this:
public class ContentMenuModel
{
#region Title
/// <summary>
/// The <see cref="Title" /> property's name.
/// </summary>
public const string TitlePropertyName = "Title";
private string _Title = String.Empty;
/// <summary>
/// Gets the Title property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[Required]
[StringLength(128, ErrorMessage = "The Title value cannot exceed 128 characters. ")]
public string Title
{
get
{
return _Title;
}
set
{
if (_Title == value)
{
return;
}
var oldValue = _Title;
_Title = value;
// Update bindings, no broadcast
RaisePropertyChanged(TitlePropertyName);
}
}
#endregion
#region Options
/// <summary>
/// The <see cref="Options" /> property's name.
/// </summary>
public const string OptionsPropertyName = "Options";
private ObservableCollection<ContentMenuOptionModel> _Options = null;
/// <summary>
/// Gets the Options property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ObservableCollection<ContentMenuOptionModel> Options
{
get
{
return _Options;
}
set
{
if (_Options == value)
{
return;
}
var oldValue = _Options;
_Options = value;
RaisePropertyChanged(OptionsPropertyName);
}
}
#endregion
#region ContextText
/// <summary>
/// The <see cref="Options" /> property's name.
/// </summary>
public const string ContextTextPropertyName = "ContextText";
private ContentPageItem _ContextText = null;
/// <summary>
/// Gets the ContextText property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ContentPageItem ContextText
{
get
{
return _ContextText;
}
set
{
if (_ContextText == value)
{
return;
}
_ContextText = value;
RaisePropertyChanged(OptionsPropertyName);
}
}
#endregion
}
I had binded the ViewModelLocator to my mainwindow’s DataContext and Path=ViewModel’s MainMenu, so the MainMain is the object of the ViewModel where I can bind this Property to the ListView’s ItemsSource, but it is not working.
Please correct me where I am wrong.
In order to get full example quickly, you can install NUGet for Visual Studio and install MVVMLight package through it on a clean WPF Application project. Then it will set everything up, and you will see how it works.
Though I’ll describe the basics here.
MVVMLight supports this out of the box. Standard template for MVVMLigth includes
ViewModelLocatorand aMainViewModel.ViewModelLocator– is the class that holds all other view models. From the start it has only one propertypublic MainViewModel Main {get;}.ViewModelLocatoris registered as a resource in App.xamlThen, on any page, if you want to get to the view model, you should simply reference Locator resource and get its property that is appropriate for your page. Here’s example for
MainWindowand itsMainViewModel:In the example above, I’ve added
public string Text {get;}property toMainViewModeland referenced. In example there is no need for any code-behind, everyting is setup declaratively via xaml.