This app is displaying the class name of a collection instead of a text-box as desired. I've read other issues with this, but cannot figure out what I'm missing. I have a datacontext, I'm bound to the collection as an itemsource, and I've added a single item. All I want is to bind the collection 'Boxes' in my view model 'DrawBoxViewModel' to an item source, and have it display a single item as a text box. All help is appreciated.
First my XAML:
<Page
x:Class="BoxMaker2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BoxMaker2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:BoxMaker2.ViewModels"
mc:Ignorable="d">
<Page.Resources>
<vm:DrawBoxViewModel x:Key="DrawBoxViewModel"/>
</Page.Resources>
<Canvas DataContext="{Binding Source={StaticResource DrawBoxViewModel}}">
<ItemsControl ItemsSource="{Binding Boxes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="350" Height="600" Background="AliceBlue"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<DataTemplate x:DataType="vm:Box" x:Key="test">
<VariableSizedWrapGrid>
<TextBox Background="White"
Text="{x:Bind Data}"
Width="100"
Height="100"/>
<VariableSizedWrapGrid.RenderTransform>
<TranslateTransform X="{Binding LeftCanvas}" Y="{Binding TopCanvas}"/>
</VariableSizedWrapGrid.RenderTransform>
</VariableSizedWrapGrid>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</Canvas>
And now my viewmodel:
namespace BoxMaker2.ViewModels
{
public class DrawBoxViewModel
{
#region fields
private ObservableCollection<Box> _boxes;
#endregion
#region properties
public ObservableCollection<Box> Boxes { get { return this._boxes; } }
#endregion
#region constructors
public DrawBoxViewModel()
{
this._boxes = new ObservableCollection<Box>();
_boxes.Add(new Box() { Data = "hello!", LeftCanvas = 200, TopCanvas = 200 });
}
#endregion
}
public class Box : INotifyPropertyChanged
{
private int _generation;
public int Generation
{
get { return _generation; }
set { _generation = value; OnPropertyChanged("Generation"); }
}
private int _childNo;
public int ChildNo
{
get { return _childNo; }
set { _childNo = value; OnPropertyChanged("ChildNo"); }
}
private Box _parentBox;
public Box ParentBox
{
get { return _parentBox; }
set { _parentBox = value; OnPropertyChanged("ParentBox"); }
}
private List<Box> _childrenBox;
public List<Box> ChildrenBox
{
get { return _childrenBox; }
set { _childrenBox = value; OnPropertyChanged("ChildrenBox"); }
}
private string _data;
public string Data
{
get { return _data; }
set
{
_data = value;
OnPropertyChanged("Data");
}
}
private double _topCanvas;
public double TopCanvas
{
get { return _topCanvas; }
set
{
_topCanvas = value;
OnPropertyChanged("TopCanvas");
}
}
private double _leftCanvas;
public double LeftCanvas
{
get { return _leftCanvas; }
set
{
_leftCanvas = value;
OnPropertyChanged("LeftCanvas");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I am not exactly sure what you are trying to achieve but here's a few issues I have found in your code.
You should assign your VM to the DataContext of the Page
directly.
<Page.DataContext>
<vm:DrawBoxViewModel />
</Page.DataContext>
After doing so, you can now remove DataContext="{Binding
Source={StaticResource DrawBoxViewModel}}" from your Canvas.
Replace <ItemsControl.Resource> with
<ItemsControl.ItemTemplate> and remove x:Key="test", assuming you want to show multiple
TextBoxes on the UI. The DataTemplate within the Resource you
defined won't do anything until you reference it by its key. I don't
think you really want that here though.
You should use x:Bind for your X & Y binding
<TranslateTransform X="{x:Bind LeftCanvas}"
Y="{x:Bind TopCanvas}" />
Your Boxes collection can be simplified as following
#region properties
public ObservableCollection<Box> Boxes { get; } = new ObservableCollection<Box>();
#endregion
#region constructors
public DrawBoxViewModel()
{
Boxes.Add(new Box() { Data = "hello!", LeftCanvas = 0, TopCanvas = 200 });
}
#endregion
Hope this helps!
Your Items control doesn't know which data template to use. Currently your view model has a template associated to it via the x:DataType="vm:Box" which is defined as a resource in the items control.
The problem is that Universal Windows Platform doesn't recognize templates associated to data types. So even though there is a template, the control doesn't know how to find it when it is rendering the collection of view models.
Automatic resolving of templates based on bound types was a function of WPF which is not available in UWP.
What that means is that in WPF you could associate a data template to a class/object via the x:DataType="Object Type" attribute of the data template (which is what you did). When the collection is bound, the rendering engine would auto-magically match the the individual items in the collection to their respective templates.
This was very powerful because if your collection had many different types of boxes for example (or things inheriting from DrawBoxViewModel) you could render each item type differently by simply defining a template. Well this is no more. Microsoft destroyed that feature in UWP.
So long story short - move the template to the page resource collection. Give it a key such as:
<Page.Resources>
<vm:DrawBoxViewModel x:Key="DrawBoxViewModel"/>
<DataTemplate x:Key="test">
<VariableSizedWrapGrid>
<TextBox Background="White"
Text="{x:Bind Data}"
Width="100"
Height="100"/>
<VariableSizedWrapGrid.RenderTransform>
<TranslateTransform X="{Binding LeftCanvas}" Y="{Binding TopCanvas}"/>
</VariableSizedWrapGrid.RenderTransform>
</VariableSizedWrapGrid>
</DataTemplate>
</Page.Resources>
Reference the template in your items control as follows:
<ItemsControl ItemsSource="{Binding Boxes} ItemTemplate={StaticResource test} ">
Related
When i add/remove items from the list the listview is registered on, the item gets added/removed accordingly. But when i change a property of the list, resulting in a different ToString() value, the Listview doesn't update the change accordingly. If i reload the data after a restart of the app from a xml file, the ListView shows it's items accordingly. So i think i can exclude an issue with my ToString method. Or is it an issue that I'm using ToSTring() at all?
Does anyone know the solution to this issue?
window.xaml:
<Window x:Class="WpfApplication1.MainWin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
DataContext="MainWindowViewModel"
Title="Baronieverwaltung für DSA" Height="1000" Width="1500"
WindowStartupLocation="CenterScreen"
WindowStyle="ThreeDBorderWindow">
<GroupBox Grid.Row="7" Grid.ColumnSpan="4" Header="Angestellte">
<ListView Height="200" ItemsSource="{Binding DieBaronie.Angestellte, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedIndex="{Binding SelectedAngestellterIndex}">
MainWindowViewModel.cs:
public class MainWindowViewModel : INotifyPropertyChanged
{
public Baronie DieBaronie { get; set; }
private void MethodThatChangesListViewItem()
{
if (SelectedAngestellterIndex > -1)
{
DieBaronie.Angestellte[SelectedAngestellterIndex].FunktionWarenschau = true;
}
//I found some threads where the solution was some variation of
//those NotifyPropertyChanged... but none work :(
NotifyPropertyChanged("DieBaronie.Angestellte");
NotifyPropertyChanged("DieBaronie");
NotifyPropertyChanged("");
NotifyPropertyChanged(null);
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
DieBaronie.cs:
public class Baronie
{
public ObservableCollection<Angestellter> Angestellte { get; set; }
Angestellter.cs:
public class Angestellter : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private Boolean _FunktionWarenschau { get; set; }
public Boolean FunktionWarenschau
{
get
{
return _FunktionWarenschau;
}
set
{
//if i add a break point here, the debugger stops here as expected - with the correct value
_FunktionWarenschau = value;
NotifyPropertyChanged();
}
}
//Method doesn't even get called after the change :(
public override string ToString()
{
String val = Name + " ";
if (_FunktionWarenschau)
{
val += "(Warenschau)";
}
return val;
}
Like you suggested, the issue is with ToString() - this is not a property, so the WPF binding engine is not aware of any need to refresh the view.
In addition, with more complex MVVM scenarios, I believe it is convention to use Properties anyway, as you may build out your views to display more complex data (e.g. images) or customize the layout of your data further (e.g. panel of images + strings).
To solve your problem, I would recommend:
Create a property in your ViewModel to bind to. Here, you could simply bind to FunktionWarenschau and Name. Alternatively, you can create a new string property and have FunktionWarenschau either update your string property or simply call NotifyPropertyChanged with the new property name passed along.
Create a DataTemplate for your ListView (untested code to give you a flavor)
<ListView Height="200"
ItemsSource="{Binding DieBaronie.Angestellte, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding SelectedAngestellterIndex}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FunktionWarenschau}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I'm new in c# UWP development and I'm trying to change the value of a TextBlock in runtime, but the binding does not work properly.
I'm binding the text property of the TextBlock in XAML to a property on a ViewModel with INotifyPropertyChanged, and the value changes every 10 seconds.
I don't know if it's the correct way to do it, can someone help me?
Thanks in advance!
this is the ViewModel code
class MainPaigeViewModel : INotifyPropertyChanged
{
public MainPaigeViewModel()
{
Task.Run(async () =>
{
Random random = new Random();
while (true)
{
await Task.Delay(10000);
int newValue = random.Next(-40, 40);
_MyValue = newValue.ToString();
Debug.WriteLine(MyValue);
}
});
}
//Properties
private string _MyValue;
public string MyValue
{
get { return _MyValue; }
set
{
_MyValue = value;
RaisePropertyChanged("MyValue");
}
}
//INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
and the XAML code
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CountDown2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ViewModels="using:CountDown2.ViewModels"
x:Class="CountDown2.MainPage"
mc:Ignorable="d">
<Page.DataContext>
<ViewModels:MainPaigeViewModel/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<RelativePanel VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="{Binding MyValue, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Width="100"
Height="40"
TextAlignment="Center"
FontSize="20"
/>
</RelativePanel>
</Grid>
</Page>
In UWP unlike silver light and WPF the default binding is One time for performance reasons. The Binding only takes place once as the application starts up. One way binding is the default of WinRT, Silverlight and wpf. Meaning the view will be updated but updating the view will not update view model. Two way binding will update both the view and the view model.
So for a <TextBlock> in the example, it is recommended to use One Way binding.
In a <TextBox> it is recommended to use Two Way binding for user input.
I found a couple small bugs that were causing the binding to fail ... so I changed the viewmodel... The private property was being used rather than public one. Since the code is updating the value in a thread, and then trying to marshal the objects across threads, a dispatcher was added. Also added a common base class for all view models. This make property binding a little easier, it stops binding issues when refactoring property names.
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync
public class MainPaigeViewModel: ViewModelBase
{
public MainPaigeViewModel()
{
Task.Run(async () =>
{
Random random = new Random();
while (true)
{
await Task.Delay(1000);
int newValue = random.Next(-40, 40);
try
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() => {
MyValue = newValue.ToString();
});
}
catch (Exception ex)
{
string s = ex.ToString();
}
Debug.WriteLine(MyValue);
}
});
}
//Properties
private string _MyValue;
public string MyValue
{
get { return _MyValue; }
set
{
_MyValue = value;
OnPropertyChanged();
}
}
}
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I also changed the view to use x:binding. I like x:binding over the old data binding because it shows binding issues at compile time rather than at runtime. This is besides the performance enhancements it gives.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<RelativePanel VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="{x:Bind viewModel.MyValue, Mode=OneWay}"
Width="100"
Height="40"
TextAlignment="Center"
FontSize="20"
/>
</RelativePanel>
</Grid>
Page behind code for x:bind
public sealed partial class MainPage : Page
{
public MainPaigeViewModel viewModel;
public MainPage()
{
this.InitializeComponent();
viewModel = new MainPaigeViewModel();
}
}
Try:Text="{Binding MyValue, Mode=TwoWay}"
I am trying to implement a create mask, on which a user can create a new technology with different versions (e.g: .NET with versions 4.5.2 and 4.6 etc.). For that I want the user to be able to dynamically add text boxes for additional versions.
A requirement for this is to use the MVVM Pattern, which i'm fairly new to. I created the following classes for this:
Entitiy Classes (using Entity Framework)
public class Tech : EntityBase
{
// Properties
public string TechName { get; set; }
// Navigation Properties
public virtual ICollection<TechVersion> TechVersions{ get; set; }
}
public class TechVersion : EntityBase
{
// Properties
public string VersionNumber { get; set; }
// Foreign Keys
//public int TechId{ get; set; }
// Navigation Properties
public virtual Tech Tech{ get; set; }
}
Technology View Model
public class TechnologyUpdateViewModel : ObservableObject
{
private string _technologyName;
public string TechnologyName
{
get
{
return _technologyName;
}
set
{
if (_technologyName != value)
{
_technologyName = value;
OnPropertyChanged("TechnologyName");
}
}
}
private ICommand _add;
public ICommand Add
{
get
{
if (_add == null)
{
_add = new RelayCommand(e => CreateTechnology());
}
return _add;
}
set
{
if (_add != value)
{
_add = value;
OnPropertyChanged("Add");
}
}
}
private void CreateTechnology()
{
// Add new Technology from ViewModel Properties
}
}
I am however having trouble with the XAML Code. Binding the Technology Name and adding a new Technology with just the name works fine (Textbox + Button).
But how do I get the dynamically created Textboxes and bind them to the ViewModel?
I've tried the approach I found here
For this I added public ObservableCollection<string> Versions { get; set; }
But most solutions try to create controls from an already filled list. I am trying to create text boxes and bind them to an empty list.
TechnologyAdd.xaml
<UserControl x:Class="Presentation.Views.TechnologyAddOrEdit"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Presentation.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
<StackPanel MaxWidth="250">
<DockPanel>
<TextBlock>Name: </TextBlock>
<TextBox Text="{Binding TechnologyName}" Margin="10,0,0,0" />
</DockPanel>
<!-- Approach from the Link -->
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<ItemsControl ItemsSource="{Binding Versions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Content="Save" Command="{Binding Add}" />
</StackPanel>
</StackPanel>
Maybe the whole MVVM thing confuses me too much but I can't seem to find a solution for this.
I would be happy about any information on how to approach this correctly.
I'm using Caliburn.Micro for WPF (using VS 2012 and targeting to .NET 4.5.1).
I have problem with binding itemsSource to ComboBox (but I investigate that in my case it happens also with other controls with ItemsSource property, like ListBox).
I have nested views (usercontrols) with viewmodels created with SimpleContainer (IoC).
Here is my problem:
Combobox is populated with items not from its view viewmodel (LanguageSelectionViewModel) but from parent view viewmodel (TopViewModel).
Also, when I removed items collection from parent viewmodel, my combobox was empty.
Code:
MainWindowView.xaml:
<Window
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
d:DataContext="{d:DesignInstance d:Type=mainWindow:MainWindowViewModel}"
>
<Grid>
<top:TopView
HorizontalAlignment="Stretch"
cal:Bind.Model="{Binding TopVM}"
/>
</Grid>
</Window>
MainWindowViewModel:
public class MainWindowViewModel : Screen
{
private TopViewModel topVm;
public TopViewModel TopVM
{
get { return topVm; }
set
{
topVm = value;
NotifyOfPropertyChange(() => TopVM);
}
}
public MainWindowViewModel(TopViewModel topVm, ContentViewModel contentVm)
{
TopVM = topVm;
TopVM.ConductWith(this);
}
}
TopView.xaml:
<UserControl>
<StackPanel Orientation="Horizontal">
<languageSelection:LanguageSelectionView cal:Bind.Model="{Binding LanguageSelectionVM}"/>
</StackPanel>
</UserControl>
TopViewModel.cs:
public class TopViewModel : Screen
{
private LanguageSelectionViewModel _languageSelectionVM;
public LanguageSelectionViewModel LanguageSelectionVM
{
get { return _languageSelectionVM; }
set
{
_languageSelectionVM = value;
NotifyOfPropertyChange(() => LanguageSelectionVM);
}
}
public TopViewModel(ClockViewModel clockVm, LanguageSelectionViewModel languageSelectionVM)
{
this.Items = new ObservableCollection<string>() { "a", "a", "a" };
LanguageSelectionVM = languageSelectionVM;
LanguageSelectionVM.ConductWith(this);
}
private ObservableCollection<string> _items;
public ObservableCollection<string> Items
{
get { return _items; }
set
{
_items = value;
NotifyOfPropertyChange(() => Items);
}
}
}
LanguageSelectionView.xaml:
<UserControl>
<StackPanel Orientation="Vertical">
<ComboBox ItemsSource="{Binding Items}"/>
</StackPanel>
</UserControl>
LanguageSelectionViewModel.cs:
public class LanguageSelectionViewModel : Screen
{
private ObservableCollection<string> _items;
public ObservableCollection<string> Items
{
get { return _items; }
set
{
_items = value;
NotifyOfPropertyChange(() => Items);
}
}
public LanguageSelectionViewModel()
{
this.Items = new ObservableCollection<string>() { "1", "a" };
}
}
I had also tried to populate this collection later, with no success:
protected override void OnViewReady(object view)
{
base.OnViewReady(view);
this.Items = new ObservableCollection<string>() { "1", "a" };
Refresh();
}
DataContext seems to be okay, because binding to textbox
<TextBlock Text="{Binding TestString}"/>
works fine.
Ok, mystery solved.
Instead of nesting controls like this:
<Grid>
<top:TopView
cal:Bind.Model="{Binding TopVM}" />
</Grid>
I should write:
<Grid>
<ContentControl
cal:View.Model="{Binding TopVM}" />
</Grid>
And there is no need to force DataContext.
I figure out that ComboBox whas the only control that had DataContext set to parent View Model, not to proper View model.
It works by forcing it in this way:
<ComboBox
DataContext="{Binding}"
ItemsSource="{Binding Items}" >
But still is the question - why? This is bug or feature of Caliburn.Micro?
I'm trying to get the databinding I need to work with a ListBox.
I've parsed some data from a text file to a ObservableCollection<ViewModel> but the data isn't updating in the ListBox.
Here's some information:
The data which is written to from the parser:
class MainData
{
private static ObservableCollection<GroupViewModel> groupModelList = new ObservableCollection<GroupViewModel>();
public static ObservableCollection<GroupViewModel> GroupModelList
{
get { return groupModelList; }
}
}
What GroupViewModel holds (not everything but it's all the same):
class GroupViewModel : INotifyPropertyChanged
{
private GroupModel groupModel;
public event PropertyChangedEventHandler PropertyChanged;
public GroupViewModel()
{
groupModel = new GroupModel();
}
public string Name
{
get { return groupModel.name; }
set
{
if (groupModel.name != value)
{
groupModel.name = value;
InvokePropertyChanged("Name");
}
}
}
...
}
And what GroupModel Holds:
class GroupModel
{
public string name { get; set; }
}
This is how the parser adds new items to the GroupModelView:
if (split[0] == "group")
{
currentGroup = new GroupViewModel();
currentGroup.Name = split[1];
MainData.GroupModelList.Add(currentGroup);
}
I created a ListBox in my WPF application with these XAML options:
<Window x:Class="SoundManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SoundManager.ViewModels"
xmlns:vm2="clr-namespace:SoundManager.Code"
Title="MainWindow" Height="720" Width="1280">
<Window.Resources>
<vm:MainViewModel x:Key="MainViewModel" />
<vm2:MainData x:Key="MainData" />
</Window.Resources>
<ListBox Grid.Row="2" Height="484" HorizontalAlignment="Left" Margin="12,0,0,0" Name="lbFoundItems" VerticalAlignment="Top" Width="201" ItemsSource="{Binding Source={StaticResource MainData}, Path=GroupModelList/Name}" />
but for some reason the data isn't updating in the UI (new items aren't added visibly in the UI).
I've been just getting started with the MVVM pattern and databinding and I can't figure out what I'm doing wrong.
Thanks in advance!
GroupModelList/Name is not a valid property path here. Setting it like that does not make the ListBox show the Name property of the data items in the GroupModelList collection.
You would instead have to set the ListBox's DisplayMemberPath property:
<ListBox ItemsSource="{Binding Source={StaticResource MainData}, Path=GroupModelList}"
DisplayMemberPath="Name"/>
or set the ItemTemplate property:
<ListBox ItemsSource="{Binding Source={StaticResource MainData}, Path=GroupModelList}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Moreover, the GroupModelList property should not be static:
class MainData
{
private ObservableCollection<GroupViewModel> groupModelList =
new ObservableCollection<GroupViewModel>();
public ObservableCollection<GroupViewModel> GroupModelList
{
get { return groupModelList; }
}
}
Then you might have MainData as a property in your view model, and bind the ListBox like this:
<ListBox ItemsSource="{Binding Source={StaticResource MainViewModel},
Path=MainData.GroupModelList}" .../>