I have a problem with binding my usercontrol to object in mainwindow. I don't know what is wrong.
I created custom control MyUserControl which has editable textbox
MyUsrControl.xaml
<UserControl x:Class="UserControlToObject.MyUsrControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="70" d:DesignWidth="200">
<StackPanel Orientation="Horizontal">
<Label Grid.Row="0" Grid.Column="0" Margin="5">Name</Label>
<TextBox Grid.Row="0" Grid.Column="1" Margin="5" Name="tbxName"></TextBox>
</StackPanel>
</UserControl>
Next I defined DP to allow modify this textbox outside countrol
MyUsrControl.xaml.cs
namespace UserControlToObject
{
public partial class MyUsrControl : UserControl
{
public static readonly DependencyProperty EmpNameProperty = DependencyProperty.Register("EmpNameProperty", typeof(string), typeof(MyUsrControl),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, EmpNamePropertyChanged));
public string EmpName
{
get
{
return (string)GetValue(EmpNameProperty);
}
set
{
SetValue(EmpNameProperty, value);
}
}
public MyUsrControl()
{
InitializeComponent();
}
static void EmpNamePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MyUsrControl x = (MyUsrControl)sender;
x.tbxName.Text = (string)e.NewValue;
}
}
}
Next, I defined Employee class - properties of object of this class will be displayed on user control
namespace UserControlToObject
{
/// <summary>
/// Employee class
/// </summary>
class Employee : INotifyPropertyChanged
{
string m_name, m_surname;
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Employee name property
/// </summary>
public string Name
{
get { return m_name; }
set
{
m_name = value;
OnPropertyChanged("Name");
}
}
/// <summary>
/// Employee surname property
/// </summary>
public string Surname
{
get { return m_surname; }
set
{
m_surname = value;
OnPropertyChanged("Surname");
}
}
public Employee()
{
m_name = "unknown name";
m_surname = "unknown surname";
}
public Employee(string name, string surname)
{
m_name = name;
m_surname = surname;
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
And finally MainWindow.xaml
<Window x:Name="myApp" x:Class="UserControlToObject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UserControlToObject"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<local:MyUsrControl x:Name="ucEmp" EmpName="{Binding Name}"></local:MyUsrControl>
<Label Content="{Binding ElementName=ucEmp, Path=EmpName}"></Label>
</StackPanel>
</Window
>
MainWindow.xaml.cs
namespace UserControlToObject
{
public partial class MainWindow : Window
{
Employee anEmployee;
public MainWindow()
{
InitializeComponent();
anEmployee = new Employee("John", "Wayne");
this.DataContext = anEmployee;
}
}
}
This line don't work (error saying that I can set binding only on DependencyProperty... of DependencyObject):
<local:MyUsrControl x:Name="ucEmp" EmpName="{Binding Name}"></local:MyUsrControl>
Those settings below works, so I think that's problem with my Employee class (sth is missing ?)
<local:MyUsrControl x:Name="ucEmp" EmpName="John"></local:MyUsrControl> --> set EmpName ok
<Label Content="{Binding ElementName=ucEmp, Path=EmpName}"></Label> --> get EmpName ok
I've no idea whot is wrong, so will be very greatfull for help
I did the same but binding TextBox instead of user control and was no problem.
TextBox.Text is dependency property same as my Employee.EmpName
When registering the dependency property you need to use the name that you want to use in XAML. In your case, this is EmpName and not EmpNameProperty:
public static readonly DependencyProperty EmpNameProperty = DependencyProperty.
Register(nameof(EmpName), typeof(string), typeof(MyUsrControl), new
FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.
BindsTwoWayByDefault, EmpNamePropertyChanged));
"EmpNameProperty" in your property registeration should be ""EmpName"" w.
Thanks
Related
In the example below, I am using XAML to set the DataContext to a class name, not an object name (as far as I can tell). The binding works - the txtEcho textbox shows what is entered in the txtName textbox when the latter loses focus. I want to be able to access the properties of this class in code-behind so I need an object reference. I could create a Person object and set the DataContext to that but the pattern in the books I am consulting does not do that - the class name is used and an object is not explicitly created in the examples in these textbooks.
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication5"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:Person x:Key="personData" />
</Window.Resources>
<Grid>
<Grid.DataContext>
<Binding Source="{StaticResource personData}" />
</Grid.DataContext>
<TextBlock HorizontalAlignment="Left" Margin="27,41,0,0" TextWrapping="Wrap" Text="Name" VerticalAlignment="Top" Height="23"/>
<TextBox x:Name="txtName" Text="{Binding Name}" HorizontalAlignment="Left" Height="23" Margin="78,42,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txtEcho" Text="{Binding Name}" HorizontalAlignment="Left" Height="23" Margin="262,42,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
</Grid>
</Window>
The code is
namespace WpfApplication5
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//txtFreedom.Text = <what exactly?>.Name; // no object reference!
}
}
class Person : INotifyPropertyChanged
{
string name;
public string Name
{
get { return this.name; }
set
{
this.name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You could access the Person instance that you create in your XAML like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
Person person = this.Resources["personData"] as Person;
txtFreedom.Text = person.Name;
}
I found a way, with mm8's help. The code is now
namespace WpfApplication5
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static Person oPerson;
public MainWindow()
{
InitializeComponent();
oPerson = this.Resources["personData"] as Person;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
txtFreedom.Text = oPerson.Name;
}
}
public class Person : INotifyPropertyChanged
{
string name;
public string Name
{
get { return this.name; }
set
{
this.name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
The differences are, Declare a public static variable to hold a Person object.
public static Person oPerson;
In the MainWindow() method set it to the behind-the-scenes Person instance.
oPerson = this.Resources["personData"] as Person;
I had to make the class public to stop a compiler accessibility objection.
public class Person : INotifyPropertyChanged
Now I can reference the properties of the instance.
private void Button_Click(object sender, RoutedEventArgs e)
{
txtFreedom.Text = oPerson.Name;
}
In my Custom Control that have a DataGrid and two buttons, one for add rows in this DataGrid and other button to remove elements.
(because of my reputation I can not post an image here, sorry!) :-(
My Custom Control code behind:
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class CustonDatagrid : UserControl
{
public CustonDatagrid()
{
InitializeComponent();
}
#region DependencyProperty Content
/// <summary>
/// Registers a dependency property as backing store for the Content property
/// </summary>
public static readonly DependencyProperty ColectionProperty =
DependencyProperty.Register("Colection",
typeof(ObservableCollection<object>),
typeof(CustonDatagrid),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
/// <summary>
/// Gets or sets the Content.
/// </summary>
/// <value>The Content.</value>
public ObservableCollection<object> Colection
{
get { return (ObservableCollection<object>)GetValue(ColectionProperty); }
set { SetValue(ColectionProperty, value); }
}
#endregion
public static readonly RoutedEvent AddButtonEvent = EventManager.RegisterRoutedEvent(
"AddButtonClick",
RoutingStrategy.Bubble,
typeof (RoutedEventHandler),
typeof (CustonDatagrid));
public event RoutedEventHandler AddButtonClick
{
add { AddHandler(AddButtonEvent, value); }
remove { RemoveHandler(AddButtonEvent, value);}
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var newEventArgs = new RoutedEventArgs(AddButtonEvent);
RaiseEvent(newEventArgs);
}
}
My .xaml:
<UserControl x:Class="WpfCustomControlLibrary1.CustonDatagrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Name="CustonDataGrid">
<Grid>
<DockPanel LastChildFill="True" >
<StackPanel DockPanel.Dock="Bottom" HorizontalAlignment="Right" Orientation="Horizontal">
<Button Margin="5" Width="20" Click="ButtonBase_OnClick" >+</Button>
<Button Margin="5" Width="20">-</Button>
</StackPanel>
<DataGrid ItemsSource="{Binding ElementName=CustonDataGrid, Path=Colection}" DockPanel.Dock="Top"></DataGrid>
</DockPanel>
</Grid>
</UserControl>
And the usage in a wpf windows:
xaml code:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfCustomControlLibrary1="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}, Path=Model}"
>
<Grid>
<wpfCustomControlLibrary1:CustonDatagrid Colection="{Binding Path=Colection}" AddButtonClick="CustonDatagrid_OnAddButtonClick">
</wpfCustomControlLibrary1:CustonDatagrid>
</Grid>
</Window>
And the code behind + View Model + datagrid row view model:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
Model = new Model();
InitializeComponent();
}
public Model Model { get; set; }
private void CustonDatagrid_OnAddButtonClick(object sender, RoutedEventArgs e)
{
Model.AddElement();
}
}
public class Model : INotifyPropertyChanged
{
public ObservableCollection<DataGridRowModel> Colection { get; set; }
public void AddElement()
{
if (Colection == null) Colection = new ObservableCollection<DataGridRowModel>();
Colection.Add( new DataGridRowModel()
{
Name = "Test"
});
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class DataGridRowModel
{
public string Name { get; set; }
}
The problem I am having is that the Datagrid is not showing the new elements added to the Collection. When debugging I can see my collection with many elements (one for each time I click on (+) button) but this elements are not showed in view.
Can some one give a tip where I am making a mistake or (probably) missing code?!?
Thanks.
One minor mistake made by you in CustonDatagrid.xaml
<DataGrid ItemsSource="{Binding ElementName=CustonDataGrid, Path=Colection}" DockPanel.Dock="Top"></DataGrid>
There is no element called CustonDataGrid because of which the elements were never reflected.
Changed it to
<DataGrid ItemsSource="{Binding Path=Colection}"></DataGrid>
I also made minor change in your MainWindow.cs
public partial class MainWindow : Window
{
public MainWindow()
{
Model = new Model();
InitializeComponent();
this.DataContext = Model;
}
public Model Model { get; set; }
private void CustonDatagrid_OnAddButtonClick(object sender, RoutedEventArgs e)
{
Model.AddElement();
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfCustomControlLibrary1="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1"
Title="MainWindow" Height="350" Width="525">
<ScrollViewer>
<wpfCustomControlLibrary1:CustonDatagrid Colection="{Binding Colection,Mode=TwoWay}" AddButtonClick="CustonDatagrid_OnAddButtonClick">
</wpfCustomControlLibrary1:CustonDatagrid>
</ScrollViewer>
</Window>
Added a constructor for Model.cs
public class Model : INotifyPropertyChanged
{
public ObservableCollection<DataGridRowModel> Colection { get; set; }
public Model()
{
Colection = new ObservableCollection<DataGridRowModel>();
}
public void AddElement()
{
Colection.Add(new DataGridRowModel { Name = "Test" });
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
I hope it works at your end also.
I am new in WPF. I used to work in Winforms.
In Winforms I had the DataGridView that allows me to change, when I want a cell value.
Simply using:
dataGridView[columnIndex, rowIndex].Value = "New Value";
It works.
How can I accomplish this using DataGrid from WPF?
I was looking thorught stack over flow and could figure out an easy way to do this.
Thank you
Ok the simplest way to handle DataGrid is by binding to an ItemSource.
The example below shows how to bind your list and how changes upadte the DataGrid.
public partial class MainWindow : Window
{
private ObservableCollection<ConnectionItem> _connectionitems = new ObservableCollection<ConnectionItem>();
public MainWindow()
{
InitializeComponent();
ConnectionItems.Add(new ConnectionItem { Name = "Item1", Ping = "150ms" });
ConnectionItems.Add(new ConnectionItem { Name = "Item2", Ping = "122ms" });
}
public ObservableCollection<ConnectionItem> ConnectionItems
{
get { return _connectionitems; }
set { _connectionitems = value; }
}
private void button1_Click(object sender, RoutedEventArgs e)
{
// to change a value jus find the item you want in the list and change it
// because your ConnectionItem class implements INotifyPropertyChanged
// ite will automaticly update the dataGrid
// Example
ConnectionItems[0].Ping = "new ping :)";
}
}
public class ConnectionItem : INotifyPropertyChanged
{
private string _name;
private string _ping;
public string Name
{
get { return _name; }
set { _name = value; NotifyPropertyChanged("Name"); }
}
public string Ping
{
get { return _ping; }
set { _ping = value; NotifyPropertyChanged("Ping"); }
}
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notifies the property changed.
/// </summary>
/// <param name="property">The info.</param>
public void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
Xaml:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication4"
xmlns:properties="clr-namespace:WpfApplication4.Properties"
Title="MainWindow" Height="300" Width="400" Name="UI" >
<Grid>
<DataGrid Name="dataGridView" ItemsSource="{Binding ElementName=UI,Path=ConnectionItems}" Margin="0,0,0,40" />
<Button Content="Change" Height="23" HorizontalAlignment="Left" Margin="5,0,0,12" Name="button1" VerticalAlignment="Bottom" Width="75" Click="button1_Click" />
</Grid>
</Window>
i added a button to show how the data updates when you change something in your list, The class ConnectionItem is where you will store all your info for the datagrid.
Hope this helps
I want to bind a datagrid view in a user control that is docking to a main WPF form. However everytime I try to bind the data it must pre exist and won't update. Is there a way to perform this in the XAML directly to know when an event is triggered to update the datagridview rather than do it in the code behind?
Partial code of XAML:
xmlns:c="clr-namespace:TestWPFMain"
<UserControl.Resources>
<c:GridData x:Key="dataforGrid"/>
</UserControl.Resources>
<Grid>
<DataGrid Grid.Row="2" x:Name="datagridMain" ItemsSource="{Binding Source={StaticResource dataforGrid}, Path=Results, Mode=TwoWay}" />
</Grid>
Code Behind for UserControl above:
public GridControl()
{
InitializeComponent();
GridData gd = new GridData();
gd.UpdateResults();
//datagridMain.ItemsSource = gd.Results;
-- This code above will work if I uncomment but I want it to be bound
directly and was curious as I thought the mode of 'two way' would
do this. I am not certain and most examples assume property is already
set up and not being created and updated.
}
Code Class for GridData:
class PersonName
{
public string Name { get; set; }
}
class GridData
{
public ObservableCollection<PersonName> Results { get; set; }
public void UpdateResults()
{
using (EntityDataModel be = new EntityDataModel())
{
var list = be.tePersons.Select(x => new PersonName { Name = x.FirstName });
Results = new ObservableCollection<PersonName>(list);
}
}
}
To use binding like this, you need to:
Set the DataContext correctly on the DataGrid (or on one of its parent)
Implement INotifyPropertyChanged on your model class, and raise PropertyChanged in the property setter.
1)
Set your window's DataContext to the GridData object:
public GridControl()
{
InitializeComponent();
GridData gd = new GridData();
gd.UpdateResults();
this.DataContext = gd;
}
2)
Implement INotifyPropertyChanged. This ensures that your view gets notified when the Results property gets updated:
public class GridData : INotifyPropertyChanged
{
private ObservableCollection<PersonName> _results;
public ObservableCollection<PersonName> Results
{
get { return _results; }
set
{
_results = value;
RaisePropertyChanged("GridData");
}
}
// ...
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
#endregion
}
Then you can simply bind to the path relative to the data context.
<DataGrid ItemsSource="{Binding Results}" />
Note that you don't need two-way binding in this case -- that's for propagating changes from the View back to your model (ie, most useful for when there's a UI control like a text box or checkbox).
Here is an example (I used Window, but it will work the same for UserControl)
Xaml:
<Window x:Class="WpfApplication4.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" Name="UI">
<Grid>
<DataGrid Grid.Row="2" x:Name="datagridMain" ItemsSource="{Binding ElementName=UI, Path=GridData.Results, Mode=TwoWay}" />
</Grid>
</Window>
or id you want the whole DataContext:
<Window x:Class="WpfApplication4.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" Name="UI">
<Grid>
<DataGrid Grid.Row="2" x:Name="datagridMain" DataContext="{Binding ElementName=UI, Path=GridData}" ItemsSource="{Binding Results}" />
</Grid>
</Window>
Code:
You will have to implement INotifyPropertyChanged so the xaml knows GridData has changed
The ObservableCollection inside GridData as this function built-in so anytime you add remove items they will update the DataGrid control
public partial class MainWindow : Window , INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
GridData = new GridData { Results = new ObservableCollection<PersonName>() };
GridData.Results.Add(new PersonName { Name = "Test1" });
GridData.Results.Add(new PersonName { Name = "Test2" });
}
private GridData _gridData;
public GridData GridData
{
get { return _gridData; }
set { _gridData = value; NotifyPropertyChanged("GridData"); }
}
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notifies the property changed.
/// </summary>
/// <param name="info">The info.</param>
public void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Classes:
I made a small change to the update method, so it just clears and updates the existing ObservableCollection, otherwise you would have to Implement INotifypropertyChanged to this class if you assign a new ObservableCollection.
public class PersonName
{
public string Name { get; set; }
}
public class GridData
{
public GridData()
{
Results = new ObservableCollection<PersonName>()
}
public ObservableCollection<PersonName> Results { get; set; }
public void UpdateResults()
{
using (EntityDataModel be = new EntityDataModel())
{
// Just update existing list, instead of creating a new one.
Results.Clear();
be.tePersons.Select(x => new PersonName { Name = x.FirstName }).ToList().ForEach(item => Results.Add(item);
}
}
}
I've attached some WPF C# binding code - why doesn't this simple example work? (just trying to understanding binding to a custom object). That is when clicking on the button to increase the counter in the model, the label isn't updated.
<Window x:Class="testapp1.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>
<Button Height="23" HorizontalAlignment="Left" Margin="20,12,0,0"
Name="testButton" VerticalAlignment="Top" Width="126"
Click="testButton_Click" Content="Increase Counter" />
<Label Content="{Binding Path=TestCounter}" Height="37"
HorizontalAlignment="Right" Margin="0,12,122,0"
Name="testLabel2" VerticalAlignment="Top"
BorderThickness="3" MinWidth="200" />
</Grid>
</Window>
namespace testapp1
{
public partial class MainWindow : Window
{
public TestModel _model;
public MainWindow()
{
InitializeComponent();
InitializeComponent();
_model = new TestModel();
_model.TestCounter = 0;
this.DataContext = _model;
}
private void testButton_Click(object sender, RoutedEventArgs e)
{
_model.TestCounter = _model.TestCounter + 1;
Debug.WriteLine("TestCounter = " + _model.TestCounter);
}
}
public class TestModel : DependencyObject
{
public int TestCounter { get; set; }
}
}
thanks
For this simple example, consider using INotifyPropertyChanged and not DependencyProperties!
UPDATE
If you do want to use DPs, use the propdp snippet in VS2010 or Dr WPF's snippets for VS2008?
TestCounter needs to be a DepenencyProperty
public int TestCounter
{
get { return (int)GetValue(TestCounterProperty); }
set { SetValue(TestCounterProperty, value); }
}
// Using a DependencyProperty as the backing store for TestCounter.
//This enables animation, styling, binding, etc...
public static readonly DependencyProperty TestCounterProperty =
DependencyProperty.Register
("TestCounter",
typeof(int),
typeof(TestModel),
new UIPropertyMetadata(0));
You can implement the INotifyPropertyChanged interface in the System.ComponentModel namespace. I usually implement a Changed method that can take a number of property names and check for the event not being set. I do that because sometimes I have multiple properties that depend on one value and I can call one method from all of my property setters.
For instance if you had a Rectangle class with Width and Height properties and an Area read-only property that returns Width * Height, you could put Changed("Width", "Area"); in the property setter for Width.
public class TestModel : INotifyPropertyChanged
{
int m_TestCounter;
public int TestCounter {
get {
return m_TestCounter;
}
set {
m_TestCounter = value;
Changed("TestCounter");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
void Changed(params string[] propertyNames)
{
if (PropertyChanged != null)
{
foreach (string propertyName in propertyNames)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}