How do i pass a bool from the viewmodel to the view and change the value.
For example in my viewmodel i have created a bool
public bool load
{
get { return m_load; }
set
{
m_load = value;
OnPropertyChanged(this, o => o.load);
}
}
I then have my SelectedVm code
public ViewModel SelectedVm
{
get { return _selectedVm; }
set
{
_selectedVm = value;
if (_selectedVm != null && load == true)
{
_selectedVm.Load();
}
Load = false;
OnPropertyChanged(this, o => o.SelectedVm);
}
}
In my View the SelectedVm is bound twice but only on one of the bindings do i want Load to be called, hence the need to change the bool load
So in my view if i have the following
<ListView Grid.Row="1" Name="Sample"
ItemsSource="{Binding Path=SampleViewModel}"
SelectedItem="{Binding SelectedVm, Mode=TwoWay}"
IsSynchronizedWithCurrentItem="True" Width="500">
</ListView>
How do i change the bool load to either true or false
All of the above are just quick samples, i think this is probably quite simple however i am not that used to WPF and am still learning. any advice would be great
Ok if you want to get value of Load in View and you want to do it in pure MVVM pattern then create DependencyProperty of bool type in View and Bind it to Load property of VM like
public partial class MainWindow : Window
{
public static readonly DependencyProperty LoadProperty = DependencyProperty.Register("MyCustom", typeof(bool), typeof(MainWindow), new PropertyMetadata(new PropertyChangedCallback(LoadPropertyChangedCallback)));
public bool Load
{
get
{
return (bool)this.GetValue(LoadProperty) ;
}
set
{
this.SetValue(LoadProperty, value);
}
}
static void LoadPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//Do your load stuff here
}
public MainWindow()
{
InitializeComponent();
this.SetBinding(LoadProperty, new Binding("load"));
DataContext = new ViewModel();
}
}
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
load = true;
}
bool m_load;
public bool load
{
get { return m_load; }
set
{
m_load = value;
OnPropertyChanged("load");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
The code you published ensures that Load() is being called once, even with multiple bindings.
If I understand your real question correctly, you are actually asking for a way to make sure that each SelectedVM is calling Load() function once, and only once. Right?
if that so, you need to add a bool property to the ViewModel class, instead of the main class, that's all.
And then:
public ViewModel SelectedVm
{
get { return _selectedVm; }
set
{
_selectedVm = value;
if (_selectedVm != null && _selectedVm.load == true)
{
_selectedVm.Load();
_selectedVm.load = false;
}
OnPropertyChanged(this, o => o.SelectedVm);
}
}
you can keep your XAML as it is.
Related
I am new to the binding concept and got stuck with the following.
public sealed partial class MainPage : Page
{
Model model;
public MainPage()
{
this.InitializeComponent();
model = new Model();
this.DataContext = model;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
model.Name = "My New Name";
}
}
class Model : DependencyObject
{
public static DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Model), new PropertyMetadata("My Name"));
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
}
I have bound the Name property to Text property of TextView. All I need to do is, on the button click I want to update the Name value that will have to update the text box value. I thought, if I use dependency property instead of normal CLR property, I dont need to implement INotifyPropertyChanged.
But the value in the UI is not updating as expected. Am I missing something?
Thanks in advance.
There are a couple things that need to be addressed with your question. First of all, your model does not need to inherit from DependencyObject, rather it should implement INotifyPropertyChanged:
public class Model : INotifyPropertyChanged
{
string _name;
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
NotifyPropertyChanged("Name");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
An object that implements INotifyProperty can then be used as a DependencyProperty in your page/window/object:
public static readonly DependencyProperty ModelProperty = DependencyProperty.Register("Model",
typeof(Model), typeof(MainWindow));
public Model Model
{
get { return (Model)GetValue(ModelProperty); }
set { SetValue(ModelProperty, value); }
}
Finally, then, you can bind your TextBox.Text property to that in the XAML:
<Grid>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding Name}"/>
<Button Click="Button_Click">Click</Button>
</StackPanel>
</Grid>
The INotifyPropertyChanged is still necessary here because there needs to be a way for the UI to know that the model object has been updated.
I am having a binding issue I wasn't able to figure out for the past two days. I have thoroughly went through most of the relevant threads on SO, and I still wasn't able to pinpoint where my error lies.
The issue I'm having is with one of the textboxes in my program. The purpose of it is to show the file the user has selected from the file browser. I have bound the text property of it to a string called parameterFileSelected but the textbox never updates even though debugging seems to be showing that the iNotifyPropertyChanged is called and executed properly.
Please help me take a look at my code below if there are any mistakes in my code.
The textbox is part of an xaml called GenerateReports and this view is tied to the GenerateReportsViewModel as follows:
Code for setting datacontext to GenerateReportsViewModel
<Grid >
<Grid.DataContext>
<vm:GenerateReportsViewModel/>
</Grid.DataContext>
<Grid.ColumnDefinitions>
....
Code for TextBox. I have tried removing the Twoway mode, changing it to Oneway and removing the mode but there is no difference.
<TextBox Grid.Column="2" Grid.Row="1" Margin="5" Text="{Binding parameterFileSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" ></TextBox>
To get the file browser and then to pass the selected file result to the GenerateReportsViewModel, this is the function in the codebehind file. The genviewmodel is initialized in the beginning of the codebehind file as GenerateReportsViewModel genViewModel = new GenerateReportsViewModel();
private void ParaFileButtonClick(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
{
DataContext = genViewModel;
genViewModel.updateParameterFileSelected(openFileDialog.FileName.ToString());
}
}
This is the code that's called in GenerateReportsViewModel to update the parameterFileSelected string the textbox is bound to.
class GenerateReportsViewModel : ViewModelBase
{
private string _parameterFileSelected;
public string parameterFileSelected
{
get { return _parameterFileSelected; }
set { SetValue(ref _parameterFileSelected, value); }
}
public void updateParameterFileSelected(string parameterFile)
{
parameterFileSelected = parameterFile;
}
}
Here is the ViewModelBase the viewmodel is attached to.
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void SetValue<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
{
if (property != null)
{
if (property.Equals(value)) return;
}
OnPropertyChanged(propertyName);
property = value;
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
EDIT
Working Solution after Applying Kevin's Suggestions
For simplicity sake, the Datacontext was set in the XAML.
<Grid>
<Grid.DataContext>
<vm:GenerateReportsViewModel x:Name="generateReportsViewModel"/>
</Grid.DataContext>
Then, I call the string the textbox was bound to, in the viewmodel directly from code behind.
private void ParaFileButtonClick(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
{
generateReportsViewModel.parameterFileSelected = openFileDialog.FileName.ToString();
}
}
The ViewModel now uses Kevin's ViewModelBase:
public class GenerateReportsViewModel : ViewModelBase
{
public string parameterFileSelected
{
get { return this.GetValue<string>(); }
set { this.SetValue(value); }
}
}
Thank you Kevin for your solution. Now my 2-day-long problem is solved.
I found out that my previous ViewModelBase was calling iNotifyPropertyChanged but somehow when the View was updated, the value was null instead.
I'm trying to understand why using the ref keyword in your viewModel. I learned a nice way to create the BaseViewModel from the Classon and Baxter book which you can find below. The view-model implements the INotifyPropertyChanged like you did. What you did with [CallerMemberName] is great, it's really magical the way we can reference to our properties thanks to it.
The view model uses a the dictionary to store its properties. It uses a pretty neat trick of looking through the dictionnary keys to see if we contain the string name of the property.Otherwise, we will return a default T value.
public class CommonBaseViewModel: INotifyPropertyChanged
{
private Dictionary<string, object> Values { get; set; }
protected CommonBaseViewModel()
{
this.Values = new Dictionary<string, object>();
}
public event PropertyChangedEventHandler PropertyChanged;
protected T GetValue<T>([CallerMemberName] string name=null)
{
if (this.Values.ContainsKey(name))
{
return (T)this.Values[name];
}
else
{
return default(T);
}
}
protected void SetValue(object value, [CallerMemberName] string name = null)
{
this.Values[name] = value;
//notify my property
this.OnPropertyChanged(new PropertyChangedEventArgs(name));
}
protected void OnPropertyChanged([CallerMemberName] string name=null)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(name));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if(this.PropertyChanged != null)
{
this.PropertyChanged(this, e);
}
}
}
As for your GenerateReportViewModel, with the common view model that I provided you, your class then becomes :
public class GenerateReportsViewModel : CommonViewModelBase
{
private string _parameterFileSelected;
public string parameterFileSelected
{
get { return _parameterFileSelected; }
set { SetValue(ref _parameterFileSelected, value); }
}
get
{
return this.GetValue<string>();
}
set
{
this.SetValue(value);
}
public void updateParameterFileSelected(string parameterFile)
{
parameterFileSelected = parameterFile;
}
}
Oh before I forgot, I don't know if it was your intention, but your GenerateReportViewModel is private. This has some impact on your code. Don't forget that by defaut, classes are private!
As for your code behind, even though it could be consider bad practice, I recommend that you have a private field (OpenFileDialog _openFileDialog)that you construct while initializing your page. Because doing it each time your clicking your button is going to consume more data that you need your application to.
//EDIT
I have review my code,and it seemed that the property was not programmed correctly.
public class GenerateReportsViewModel : CommonViewModelBase
{
private string _parameterFileSelected;
public string parameterFileSelected
{
get
{
return this.GetValue<string>();
}
set
{
this.SetValue(value);
}
public void updateParameterFileSelected(string parameterFile)
{
parameterFileSelected = parameterFile;
}
}
More about my comment about constructing the page and binding the view model. While creating your page, you have to create the view-model for that page and then bind it to the data context.
I don't know what you do in your code, but I could provide with this sample such as
public GenerateReportView()
{
InitializeComponent();
//Some operations
var generateReportViewModel = new GenerateReportViewModel();
this.DataContext = generateReportViewModel;
}
So here I am again, asking a very similar question to yesterday. I re-factored my project in order to better follow the MVVM pattern. Now my binding is no longer working as it was yesterday. I am trying to bind the visibility of a dock panel to a button. Here is some of my code:
ViewModel:
public class SelectWaferButtonViewModel : INotifyPropertyChanged
{
private bool isClicked;
public SelectWaferButtonViewModel()
{
isClicked = false;
}
public bool IsControlVisible
{
get
{
return isClicked;
}
set
{
isClicked = value;
OnPropertyChanged("IsControlVisible");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnButtonClick()
{
if (isClicked)
{
IsControlVisible = false;
}
else
{
IsControlVisible = true;
}
}
protected virtual void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
XAML:
<Window.Resources>
<local:BoolToVisibilityConverter x:Key="BoolToVisConverter"/>
<local:SelectWaferButtonViewModel x:Key="SelectWaferButton" />
<local:WaferTrackerWindowViewModel x:Key="WindowViewModel" />
</Window.Resources>
<DockPanel
Name="tvwDockPanel"
DataContext="{StaticResource SelectWaferButton}"
Width="225"
Visibility="{Binding IsControlVisible, Mode=TwoWay,
FallbackValue=Collapsed,
Converter={StaticResource BoolToVisConverter}}"
DockPanel.Dock="Left">
</DockPanel>
My BoolToVisConverter:
public class BoolToVisibilityConverter : IValueConverter
{
public BoolToVisibilityConverter() { }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool bValue = (bool) value;
if (bValue)
{
return Visibility.Visible;
}
else
{
return Visibility.Collapsed;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Visibility visibility = (Visibility) value;
if (visibility == Visibility.Visible)
{
return true;
}
else
{
return false;
}
}
}
I apologize for a question that is similar to yesterday, but I am struggling with this MVVM stuff since I am quite new to WPF. Any help will be much appreciated.
Thanks in advanced,
EDIT:
Here is some extra code snippets for further reference:
public class WaferTrackerWindowViewModel :INotifyPropertyChanged
{
private SelectWaferButtonViewModel btnSelectWaferViewModel;
public event PropertyChangedEventHandler PropertyChanged;
private DelegateCommand exitCommand;
private DelegateCommand expandPanelCommand;
private DelegateCommand selectWaferCommand;
public WaferTrackerWindowViewModel()
{
this.InstantiateObjects();
initThread.RunWorkerAsync();
}
public string SelectedWafer
{
get
{
return selectedWafer;
}
set
{
selectedWafer = value;
}
}
public ICommand ExitCommand
{
get
{
if (exitCommand == null)
{
exitCommand = new DelegateCommand(Exit);
}
return exitCommand;
}
}
public ICommand ExpandPanelCommand
{
get
{
if (expandPanelCommand == null)
{
expandPanelCommand = new DelegateCommand(ExpandPanel);
}
return expandPanelCommand;
}
}
public ICommand SelectWaferCommand
{
get
{
if (selectWaferCommand == null)
{
selectWaferCommand = new DelegateCommand(SelectWafer);
}
return selectWaferCommand;
}
}
private void InstantiateObjects()
{
btnSelectWaferViewModel = new SelectWaferButtonViewModel();
initThread = new BackgroundWorker();
}
private void ExpandPanel()
{
btnSelectWaferViewModel.OnButtonClick();
}
private void SelectWafer()
{
//Does Nothing Yet
}
private void Exit()
{
Application.Current.Shutdown();
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private void InitThread_DoWork(object sender, DoWorkEventArgs e)
{
TreeViewPresenter tvwPresenter = new TreeViewPresenter();
tvwPresenter.WaferList = DataLibrary.GetWaferList();
}
private void InitThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
tvwPresenter.TreeView.DataContext = tvwPresenter.ProcessesAndWafers;
tvwPresenter.WaferListCache = tvwPresenter.ProcessesAndWafers;
tvwPresenter.ProcessArray = tvwPresenter.WaferListCache.ToArray();
}
}
When the "expand panel" button gets clicked, it calls the ExpandPanel command, which routes the execution to the method "private void ExpandPanel()" in this same class. Then, in the ExpandPanel() method, it calls the OnButtonClick() method on the btnSelectWaferViewModel object, which will change the IsControlVisible property. This change should then be reflected onto the bound dock panel, but this is not happening
Kyle
(1) ViewModel should be in the Window.DataContext section, not the Window.Resources section.
(2) In your view model, make your IsControlVisible property a System.Windows.Visibility, rather than a Boolean, then you don't need a converter.
(3) I don't see any way for OnButtonClick to fire, and it really needs to be set up with ICommand interface.
(4) You don't need to implement ConvertBack because the Visibility property you're binding to is one way by definition. There is no way for the user to set the visibility to false.
(5) Don't mix accessing IsClicked and it's accessor IsControlVisible. Always use the Accessor in MVVM, because you run the risk of accidentally setting IsClicked which won't activate OnPropertyChanged.
All in all, you're pretty close. Make sure to keep an eye on your "Output" window, it will tell you if a binding is failing for some reason. But yeah, hang in there!
So when you do this:
<Window.Resources>
<local:SelectWaferButtonViewModel x:Key="SelectWaferButton" />
</Window.Resources>
WPF will create a new instance of the SelectWaferButtonViewModel and add it to it's resources. You then bind to this by setting the DataContext using the StaticResource with the key.
However, if you are then creating another SelectWaferButtonViewModel in your code behind and linking up your command to that instance, then it's not the same instance, so changes to the properties of this unbound instance won't effect your UI. There are a couple of ways around it. You can either a) create a single SelectWaferButtonViewModel in the code behind as a property and then bind to that in XAML, or b) Declare your SelectWaferButtonViewModel in XAML as you currently have it and then retrieve that instance in your code behind, like this:
SelectWaferButtonViewModel swbvm = (SelectWaferButtonViewModel)this.FindResource("SelectWaferButton");
Edit: So after seeing your last edit, if you want to go with a) then I would suggest you expose btnSelectWaferViewModel as a property in your WaferTrackerWindowViewModel and then bind to that property with the DataContext of your Window set to the WaferTrackerWindowViewModel instance. So you end up with something like:
<DockPanel
Name="tvwDockPanel"
Width="225"
Visibility="{Binding MyButton.IsControlVisible,
Converter={StaticResource BoolToVisConverter}}"
DockPanel.Dock="Left">
</DockPanel>
and:
public class WaferTrackerWindowViewModel :INotifyPropertyChanged
{
private SelectWaferButtonViewModel btnSelectWaferViewModel;
public SelectWaferButtonViewModel MyButton
{
get { return btnSelectWaferViewModel; }
set
{
btnSelectWaferViewModel = value;
OnPropertyChanged("MyButton");
}
}
//......
There must be a lot of questions surrounding this area but I couldn't find anything to help in my instance.
The problem I'm experiencing is getting my ViewModel, and specifically a property within ViewModel, to be updated to my View. Below is my implementation. I think I understand where I'm going wrong but not sure how to resolve it.
I have a Module that has a list and edit view. Quite simply lists domain objects and then ability to edit a domain object.
My xaml binds the DataContent to a ViewModel property in my View.
I then use the INavigationAware.NavigateTo method to navigate to my ViewModel and this is where I load the domain object.
The problem is that obviously this is not reflected back to the View. The view already has an instance of the ViewModel. This method worked fine when the ViewModel was using a list of objects using ObservableCollection. However, this did not work when using a simple object or even an ObservableObject.
Could someone please help my understanding or point me to some links with a better implementation of what I am trying to achieve?
MyModule
public class MyModule : IModule
{
private readonly IRegionManager _regionManager;
public MyModule(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public void Initialize()
{
_regionManager.RegisterViewWithRegion(Constants.MainRegionName, typeof(MyListView));
_regionManager.RegisterViewWithRegion(Constants.MainRegionName, typeof(MyEditView));
}
}
XAML
<UserControl
DataContext="ViewModel">
...
<TextBlock Text="{Binding Path=MyDomainObject.AProperty}" />
...
View
public partial class MyEditView
{
public readonly static string ViewName = "MyEditView";
public MyEditView(MyEditViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
}
public MyEditViewModel ViewModel
{
get { return DataContext as MyEditViewModel; }
private set { DataContext = value; }
}
}
ViewModel
public class MyViewModel : INavigationAware
{
private readonly IRegionManager _regionManager;
public MyDomainObject MyDomainObject { get; set; }
public void Load(ViewModelKey key)
{
// get domain object
// this method worked when MyDomainObject was
// ObservableCollection<T> as just adding elements to list
// where this is creating a new instance of MyDomainObject
var id = parameter from navigationContext;
MyDomainObejct = server.GetDomainObject(id);
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
var key = key from navigationContext;
Load(key);
}
}
SOLUTION
public class MyEditViewModel : INavigationAware
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private MyDomainObject _myDomainObject;
public MyDomainObject MyDomainObject
{
get
{
return _myDomainObject;
}
set
{
if (value != _myDomainObject)
{
_myDomainObject = value;
NotifyPropertyChanged();
}
}
}
View
public partial class MyEditView
{
public MyEditView(MyEditViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
ViewModel.PropertyChanged += ViewModel_PropertyChanged;
}
public MyEditViewModel ViewModel
{
get { return DataContext as MyEditViewModel; }
private set { DataContext = value; }
}
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (!(sender is MyEditViewModel))
return;
ViewModel = (MyEditViewModel)sender;
}
}
For your binding to update you need to implement INotifyPropertyChanged and raise PropertyChanged Event on the set accessor of your domain object.
public event PropertyChangedEventHandler PropertyChanged = delegate {};
public MyDomainObject MyDomainObject
{
get
{
return myDomainObject;
}
set
{
if(value != myDomainObject)
{
myDomainObject = value;
RaisePropertyChanged("MyDomainObject");
}
}
}
private void RaisePropertyChanged(String p)
{
PropertyChanged(this, new PropertyChangedEventArgs(p));
}
Or as in the Prism book, inherit NotificationObject and call RaisePropertyChanged(()=> PropertyName) which is refactoring-safe
I have a UserControl, we'll call it "Header". It has a DependencyProperty called ProjectID, this control has a View Model and I set it to be the DataContext:
public BillingInfoHeaderControlVM VM
{
get
{
return (BillingInfoHeaderControlVM)DataContext;
}
set
{
DataContext = value;
}
}
public static readonly DependencyProperty ProjectIDProperty =
DependencyProperty.Register("ProjectID", typeof(int), typeof(BillingInfoHeaderControl), new PropertyMetadata();
public int ProjectID
{
set
{
SetValue(ProjectIDProperty, value);
}
get
{
return (int)GetValue(ProjectIDProperty);
}
}
Now what I want to do, is to bind the ProjectID of a control to this control's ProjectID:
<controls:Header Grid.Row ="0" x:Name="Header" ProjectID="{Binding ProjectID, Mode=OneWay}"></controls:Header>
Now when I run this, I get an error in the InitializeControl() method that states "
Property Get method was not found.
From what I'm reading, I'm seeing this is because the Binding ProjectID is relative to the data context of the control. Of course I could set the ElementName within the binding:
<controls:Header Grid.Row ="0" x:Name="Header" ProjectID="{Binding ProjectID, Mode=OneWay, ElementName=ParentControl}"></controls:Header>
But this is ugly, and to be honest we don't want to have to remember to do this for this control whenever we use it. What other options do I have? Is there a way to set the source of the binding to use the DataContext of the parent?
I duplicated your concept in code and it compiles and runs fine.
I have included the control code and the viewmodel below in case you are doing something different.
*Note: I kept the viewmodel ProjectID as a simple update property.:
namespace Demo1
{
public partial class BillingInfoHeaderControl : UserControl
{
public BillingInfoHeaderControl()
{
InitializeComponent();
this.DataContext = new BillingInfoHeaderControlVM();
}
public int ProjectId
{
get { return (int)GetValue(ProjectIdProperty); }
set { SetValue(ProjectIdProperty, value); }
}
public static readonly DependencyProperty ProjectIdProperty =
DependencyProperty.Register("ProjectId", typeof(int), typeof(BillingInfoHeaderControl),
new PropertyMetadata(0));
}
}
namespace Demo1
{
public class BillingInfoHeaderControlVM : INotifyPropertyChanged
{
private int _projectId;
public int ProjectId
{
get { return _projectId; }
set
{
if (_projectId != value)
{
_projectId = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ProjectId"));
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}