The following problem makes me crazy, for the last 2 days i spent my afternoons trying to solve the problem, so i really tried to research it.
My problem is that, when i'm using databinding to a treeview, it doesn't seem to work. I'm probably missing something, and i'd like to kindly ask your help finding it.
For the WPF XAML i'm using the following code:
<Window x:Class="MesDiag2.MainWindow"
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:MesDiag2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding Materials}" DataType="{x:Type local:ProductNode}">
<Label Content="{Binding Product.LotName}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding Root}">
</TreeView>
</Grid>
My classes are the following, note that this is only a "test" project i made to see where the problem is. I've tried to make everything as simple as possible. The INotifyPropertyChanged for every class was just a desperate attempt to see if it fixes it:
using System.ComponentModel;
namespace MesDiag2
{
public class Product : INotifyPropertyChanged
{
string lotName;
public string LotName
{
get { return lotName; }
set
{
lotName = value;
NotifyPropertyChanged("LotName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
The context of the TreeViewItem should be the following class:
using System.Collections.Generic;
using System.ComponentModel;
namespace MesDiag2
{
public class ProductNode : INotifyPropertyChanged
{
Product product;
List<Product> materials;
public ProductNode(Product product)
{
Materials = new List<Product>();
Product = product;
}
public Product Product
{
get { return product; }
set
{
product = value;
NotifyPropertyChanged("Product");
}
}
public List<Product> Materials
{
get { return materials; }
set
{
materials = value;
NotifyPropertyChanged("Materials");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
My ViewModel:
using System.ComponentModel;
namespace MesDiag2
{
public class ViewModel : INotifyPropertyChanged
{
public ProductNode Root { get; set; }
public string Test { get; set; }
public ViewModel()
{
Root = new ProductNode(new Product { LotName = "Test" });
Test = "Hello";
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
And finally the content of my MainWindow class:
using System.Windows;
namespace MesDiag2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}
}
Its been a little while since I've done WPF, but I think you want to do something like this:
<TreeView ItemsSource="{Binding Root.Materials}">
<HierarchicalDataTemplate>
<Label Content="{Binding LotName}"/>
</HierarchicalDataTemplate>
</TreeView>
I'd also make:
List<Product> materials;
this:
ObservableCollection<Product> materials
https://learn.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.observablecollection-1?view=netframework-4.8
Related
I am still fairly new to binding in WPF, and I am curious to know how to properly determine the parent of a given DataContext when it it's binding is nested.
I have created some sample code to reconstruct my problem. But unfortunately the INotifyPropertyChanged (which is required for the presentation layer to update) makes the constructors rather large, the data in this example code is simply:
The parents list contains:
While the presentation is laid out with the MainWindow presenting each parent in a ParentUserControl. Which in turn then presents the associated Children in a ChildUserControl.
With the code as follows, what is the best way for the code behind to identify the parent of the button that was pressed?
MainWindow.xaml:
<Window x:Class="BindingProblem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindingProblem">
<StackPanel>
<ItemsControl ItemsSource="{Binding .}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<local:ParentUserControl></local:ParentUserControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
MainWindow.xaml.cs: (Also contains definitions for ParentClass and ChildClass)
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
namespace BindingProblem
{
public partial class MainWindow : Window
{
public List<ParentClass> data = new List<ParentClass>(){
new ParentClass()
{
ParentName = "Parent A",
children = new List<ChildClass>(){
new ChildClass() {ChildName = "Child 1"},
new ChildClass() {ChildName = "Child 2"}
}
},
new ParentClass()
{
ParentName = "Parent B",
children = new List<ChildClass>(){
new ChildClass() {ChildName = "Child 3"},
new ChildClass() {ChildName = "Child 4"}
}
}
};
public MainWindow()
{
InitializeComponent();
this.DataContext = data;
}
}
public class ParentClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string p) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p)); }
private string _ParentName;
public string ParentName
{
get { return _ParentName; }
set { _ParentName = value; NotifyPropertyChanged("ParentName"); }
}
private List<ChildClass> _children;
public List<ChildClass> children
{
get { return _children; }
set { _children = value; NotifyPropertyChanged("children"); }
}
}
public class ChildClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string p)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
}
private string _ChildName;
public string ChildName
{
get { return _ChildName; }
set { _ChildName = value; NotifyPropertyChanged("ChildName"); }
}
}
}
ParentUserControl.xaml:
<UserControl x:Class="BindingProblem.ParentUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindingProblem">
<StackPanel>
<TextBlock Text="{Binding ParentName}"></TextBlock>
<ItemsControl ItemsSource="{Binding children}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<local:ChildUserControl></local:ChildUserControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</UserControl>
ParentUserControl.xaml.cs:
using System.Windows.Controls;
namespace BindingProblem
{
public partial class ParentUserControl : UserControl
{
public ParentUserControl()
{
InitializeComponent();
}
}
}
ChildUserControl.xaml:
<UserControl x:Class="BindingProblem.ChildUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="20,0">
<TextBlock Text="{Binding ChildName}"></TextBlock>
<Button Content="Click Me" Click="Button_Click"></Button>
</StackPanel>
</UserControl>
ChildUserControl.xaml.cs:
using System;
using System.Windows;
using System.Windows.Controls;
namespace BindingProblem
{
public partial class ChildUserControl : UserControl
{
public ChildUserControl()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine(((ChildClass)DataContext).ChildName);// this works to get my data for the child
// How would I find the ParentName Feild of the parent assosiated to this child.
}
}
}
You have several options of achieving this:
You can walk up the visual tree in code behind by recursively calling the method GetParent of the VisualTreeHelper until you get the type of ParentUserControl. You can then access its DataContext property.
You can bind to the parent’s DataContext in XAML with {Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type yourNamespace:ParentUserControl}}, Path=DataContext}. If you bind this to the Tag property of the button, you could then get the reference from code behind.
You can create a property on the child view model of the type ICommand. The instance of this command is then created by the parent view model and the parent view models injects a reference to itself when doing so. Then it sets the child‘s property to the new command object. I this approach you don‘t use event handlers on the ChildUserControl, but bind the Button‘s command property to the command of the child view model. That way the command code will have a reference to the parent view model.
One simple solution is, each child can be given ParentName, so your ChildClass can become
public class ChildClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string p)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
}
public string ParentName {get;set;}
private string _ChildName;
public string ChildName
{
get { return _ChildName; }
set { _ChildName = value; NotifyPropertyChanged("ChildName"); }
}
}
when you instantiate ChildClass to add as items to the parent's children, just provide them the name of parent in which they are being added,
and then in the Click Event
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine(((sender as Button).DataContext as ChildClass).ParentName);
}
I hope somebody can help me out here. Simplified the code for posting.
We have a main window (MvvmTestView) with a menu, and a 2nd window (SettingsView) which holds several tabs. I can open the SettingsView window alright. I can even select which Tab to open by setting this in the code.
How can I get back the correct value with the command parameter from the XAML code so that the correct tab opens?
MvvmTestView.xaml:
<Window x:Class="MvvmTest.Views.MvvmTestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MvvmTest.ViewModels"
WindowStartupLocation="CenterScreen"
Title="MvvmTestView"
Height="500"
Width="500">
<Window.DataContext>
<vm:MvvmTestViewModel/>
</Window.DataContext>
<Grid>
<DockPanel>
<Menu>
<MenuItem Header="Menu">
<MenuItem
Header="Tab01"
Command="{Binding SettingsViewCommand}"
CommandParameter="0"/>
<MenuItem
Header="Tab02"
Command="{Binding SettingsViewCommand}"
CommandParameter="1"/>
</MenuItem>
</Menu>
</DockPanel>
<DockPanel>
<Label Content="MainView" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</DockPanel>
</Grid>
</Window>
SettingView.xaml
<Window x:Class="MvvmTest.Views.SettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tabData="clr-namespace:MvvmTest.Views"
xmlns:vm="clr-namespace:MvvmTest.ViewModels"
WindowStartupLocation="CenterScreen"
Title="SettingsView"
Height="400"
Width="400">
<Window.DataContext>
<vm:MvvmTestViewModel/>
</Window.DataContext>
<Grid>
<TabControl
SelectedIndex="{Binding SettingsSelectedIndex, Mode=TwoWay}">
<tabData:Tab01View/>
<tabData:Tab02View/>
</TabControl>
</Grid>
</Window>
SettingsViewModel.cs
using System.ComponentModel;
namespace MvvmTest.ViewModels
{
public class SettingsViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
private int _settingsSelectedIndex;
public int SettingsSelectedIndex
{
get
{
return _settingsSelectedIndex;
}
set
{
_settingsSelectedIndex = value;
OnPropertyChanged("SettingsSelectedIndex");
}
}
}
}
MvvmTestViewModel.cs
using MvvmTest.Commands;
using MvvmTest.Views;
using System.ComponentModel;
using System.Windows.Input;
namespace MvvmTest.ViewModels
{
internal class MvvmTestViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private SettingsViewModel SettingsViewModel;
public MvvmTestViewModel()
{
SettingsViewModel = new SettingsViewModel();
SettingsViewCommand = new SettingsViewCommand(this);
}
public ICommand SettingsViewCommand
{
get;
private set;
}
public void SettingsWindow()
{
SetIndex();
SettingsView settingsView = new SettingsView()
{
DataContext = SettingsViewModel
};
settingsView.ShowDialog();
}
public int SetIndex()
{
SettingsViewModel.SettingsSelectedIndex = 1;
return SettingsViewModel.SettingsSelectedIndex;
}
}
}
SettingsViewCommand.cs
using MvvmTest.ViewModels;
using System;
using System.Windows.Input;
namespace MvvmTest.Commands
{
internal class SettingsViewCommand : ICommand
{
private MvvmTestViewModel settingsViewModel;
public SettingsViewCommand(MvvmTestViewModel settingsViewModel)
{
this.settingsViewModel = settingsViewModel;
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
settingsViewModel.SettingsWindow();
}
}
}
I suggest to avoid creating multiple command classes like SettingsViewCommand : ICommand. Instead use some general-purpose command class (e.g. RelayCommand from MvvmFoundation NuGet package)
assuming you added MvvmFoundation to your project, refactor MvvmTestViewModel class like this:
internal class MvvmTestViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private SettingsViewModel SettingsViewModel;
public MvvmTestViewModel()
{
SettingsViewModel = new SettingsViewModel();
SettingsViewCommand = new RelayCommand<int>(SettingsWindow);
}
public ICommand SettingsViewCommand
{
get;
private set;
}
public void SettingsWindow(int index)
{
SettingsViewModel.SettingsSelectedIndex = index;
SettingsView settingsView = new SettingsView()
{
DataContext = SettingsViewModel
};
settingsView.ShowDialog();
}
}
CommandParameter from a view is passed to SettingsWindow method in a viewModel and used to change selected index
I'm trying to reorder listView items with a mouse and I'm getting this mysterious Parameter is not valid ArgumentException either when I'm starting to drag or when I'm dropping item. There are no other details, no stack trace. Crashes entire app.
It works fine when I'm reordering ObservableCollection<string> but keeps crashing on ObservableCollection<MyControl>
MyControl is just a simple UserControl with a TextBlock inside.
I tried CollectionViewSource approach and it's the same.
Any ideas?
MainPage.xaml
<Page
x:Class="App3.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ListView ItemsSource="{Binding Items}" CanReorderItems="True" AllowDrop="True"/>
</Page>
MainPage.xaml.cs
using Windows.UI.Xaml.Controls;
namespace App3
{
public sealed partial class MainPage : Page
{
private MainPageViewModel mainPageViewModel;
public MainPage()
{
this.InitializeComponent();
mainPageViewModel = new MainPageViewModel();
DataContext = mainPageViewModel;
// THIS IS NOT WORKING
MyControl myControl1 = new MyControl("Hello1");
MyControl myControl2 = new MyControl("Hello2");
MyControl myControl3 = new MyControl("Hello3");
mainPageViewModel.Items.Add(myControl1);
mainPageViewModel.Items.Add(myControl2);
mainPageViewModel.Items.Add(myControl3);
// THIS IS WORKING
//string s1 = "h1";
//string s2 = "h2";
//string s3 = "h3";
//mainPageViewModel.Items.Add(s1);
//mainPageViewModel.Items.Add(s2);
//mainPageViewModel.Items.Add(s3);
}
}
}
MainPageViewModel.cs
using System.Collections.ObjectModel;
namespace App3
{
public class MainPageViewModel : BaseModel
{
// THIS IS NOT WORKING
private ObservableCollection<MyControl> items = new ObservableCollection<MyControl>();
public ObservableCollection<MyControl> Items
{
get { return items; }
set
{
items = value;
OnPropertyChanged();
}
}
// THIS IS WORKING
//private ObservableCollection<string> items = new ObservableCollection<string>();
//public ObservableCollection<string> Items
//{
// get { return items; }
// set
// {
// items = value;
// OnPropertyChanged();
// }
//}
}
}
MyControl.xaml
<UserControl
x:Class="App3.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<TextBlock Name="tb"/>
</UserControl>
MyControl.cs
using Windows.UI.Xaml.Controls;
namespace App3
{
public sealed partial class MyControl : UserControl
{
public MyControl(string sName)
{
this.InitializeComponent();
tb.Text = sName;
}
}
}
BaseModel.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace App3
{
public class BaseModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName]string name = "")
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
EDIT
Looks like there's also no problem with reordering simple objects, so I guess there is something wrong with reordering UserControl.
namespace App3
{
public class SampleClass
{
private string sName;
public SampleClass(string sName)
{
this.sName = sName;
}
public override string ToString()
{
return sName;
}
}
}
EDIT 2
Reordering objects that derive from CheckBox crashes exactly like MyControl.
using Windows.UI.Xaml.Controls;
namespace App3
{
public class MyCheckBox : CheckBox
{
public MyCheckBox(string sName)
{
Content = sName;
}
}
}
Same for standard checkBoxes
CheckBox checkBox1 = new CheckBox() { Content = "hello1" };
CheckBox checkBox2 = new CheckBox() { Content = "hello2" };
CheckBox checkBox3 = new CheckBox() { Content = "hello3" };
mainPageViewModel.Items.Add(checkBox1);
mainPageViewModel.Items.Add(checkBox2);
mainPageViewModel.Items.Add(checkBox3);
EDIT 3
Seems like the only solution is to use simple class for holding data
using Windows.UI.Xaml.Controls;
namespace App3
{
public class MyCheckBox : BaseModel
{
private string sName;
public string Name
{
get { return sName; }
set
{
sName = value;
OnPropertyChanged();
}
}
public MyCheckBox(string sName)
{
Name = sName;
}
}
}
and DataTemplate for ListViewItem to display it
<Page
x:Class="App3.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ListView ItemsSource="{Binding Items}" CanReorderItems="True" AllowDrop="True">
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Page>
instead of adding UserControl directly to ListView items.
It looks like the reordering of Visuals is not supported entirely. When reorganizing items in a listview, a lot happens underneath, as for example dynamically creating and destroying containers that hold your content, etc.
In order to display the resorted element, some items need to be appended elsewhere in the visual tree.
The drag/drop tries to attach an already attached Visual (your UserControl) which might cause the exception - a Visual can not be attached to multiple parents.
Your approach of using POCOs / ViewModels with Datatemplates should be sufficient to get the work done, as the de- and attach semantics are considered by ListView already.
There should be more exception details, though.
I'm trying to create a simple WPF Application using data binding.
The code seems fine, but my view is not updating when I'm updating my property.
Here's my XAML:
<Window x:Class="Calculator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:calculator="clr-namespace:Calculator"
Title="MainWindow" Height="350" Width="525"
Name="MainWindowName">
<Grid>
<Label Name="MyLabel" Background="LightGray" FontSize="17pt" HorizontalContentAlignment="Right" Margin="10,10,10,0" VerticalAlignment="Top" Height="40"
Content="{Binding Path=CalculatorOutput, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
Here's my code-behind:
namespace Calculator
{
public partial class MainWindow
{
public MainWindow()
{
DataContext = new CalculatorViewModel();
InitializeComponent();
}
}
}
Here's my view-model
namespace Calculator
{
public class CalculatorViewModel : INotifyPropertyChanged
{
private String _calculatorOutput;
private String CalculatorOutput
{
set
{
_calculatorOutput = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I'm can't see what I am missing here?? o.O
CalculatorOutput has no getter. How should the View get the value? The Property has to be public as well.
public String CalculatorOutput
{
get { return _calculatorOutput; }
set
{
_calculatorOutput = value;
NotifyPropertyChanged();
}
}
I cannot get any display from my observable collection in a custom object bound to a ListBox. This works fine when I have a string collection in my view model, but no names display when I try to access the property through a custom object. I am not receiving any errors in the output window.
Here is my code:
Custom Object
public class TestObject
{
public ObservableCollection<string> List { get; set; }
public static TestObject GetList()
{
string[] list = new string[] { "Bob", "Bill" };
return new TestObject
{
List = new ObservableCollection<string>(list)
};
}
}
Xaml
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox Height="100" HorizontalAlignment="Left" Margin="120,61,0,0" Name="listBox1" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Path=TObj.List}" />
</Grid>
Xaml.cs
public partial class MainWindow : Window
{
private ModelMainWindow model;
public MainWindow()
{
InitializeComponent();
model = new ModelMainWindow();
this.DataContext = model;
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
public void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.model.Refresh();
}
}
ViewModel
public class ModelMainWindow : INotifyPropertyChanged
{
private TestObject tObj;
public event PropertyChangedEventHandler PropertyChanged;
public TestObject TObj
{
get
{
return this.tObj;
}
set
{
this.tObj = value;
this.Notify("Names");
}
}
public void Notify(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
public void Refresh()
{
this.TObj = TestObject.GetList();
}
}
Can't bind to private properties. Also the change notification targets the wrong property, change "Names" to "TObj". (Also i would recommend making the List property get-only (backed by a readonly field), or implementing INoptifyPropertyChanged so the changes cannot get lost)
Your List is private. Make it a public property otherwise WPF can't see it.