Change Binding at runtime and save class instance WPF - wpf

I am writing a WPF program write a program on .NET 4.5 which will hold a lot of settings inside and I am faced with several problems.
For example, I have a camera and I need to create another instance of that camera settings at runtime. For XAML page I have a lot of bindings and now for the second instance I need to clear them an use bindings for new instance of that class in which I hold properties for that settings (If I am thinking correctly, of course) So, I have 2 questions:
How do I change my binding so that I can write the minimum amount of code possible (please, keep in mind that I don't know how many instances will be created)?
How I can create second, third, etc. instances of a class and to lose objects in memory because I need to hold every instance of each class during runtime and just change bindings while switching between these instances.

Create a view model that manages and exposes the settings for you. Use an additional property to provide the currently selected settings:
public class CameraSettings
{
public string Title { get; set; }
public bool Grayscale { get; set; }
}
public class CameraViewModel : INotifyPropertyChanged
{
private CameraSettings _SelectedSettings;
private List<CameraSettings> _Settings;
public event PropertyChangedEventHandler PropertyChanged;
public IEnumerable<CameraSettings> Settings
{
get { return _Settings; }
}
public CameraSettings SelectedSettings
{
get { return _SelectedSettings; }
set
{
if (_SelectedSettings != value)
{
_SelectedSettings = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("SelectedSettings"));
}
}
}
}
public CameraViewModel()
{
_Settings = new List<CameraSettings>()
{
{ new CameraSettings() { Title = "BlackWhite", Grayscale = true } },
{ new CameraSettings() { Title = "TrueColor", Grayscale = false } }
};
}
}
Then you can bind your view to this view model. Example view:
<Window.DataContext>
<local:CameraViewModel />
</Window.DataContext>
<StackPanel>
<ComboBox ItemsSource="{Binding Settings}" SelectedItem="{Binding SelectedSettings, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Title}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="{Binding SelectedSettings.Grayscale}" />
</StackPanel>

Related

Populate ListBox on Selecting TreeView node in WPF using MVVM

I am developing an application in WPF in which I want to populate a ListBox on selecting a node of a TreeView. I have populated the TreeView using MVVM pattern. It actually contains the the drives (C:\, D:...) and their corresponding sub-folders. The sub-folders are the nodes. On selecting these nodes the respective files should be shown in the ListBox. I know the C# code to get all the files in a folders, I have also implemented the same. However, I am not getting any clue to map them, so that on selecting the nodes the files in them should get reflected in the ListBox.
Can any please help me in this regard? The application is being developed in MVVM pattern and I need in the same pattern itself.
First add a Files collection class to your folder class (used in the tree view)
public class FolderItem
{
// other class code
private ObservableCollection<File> _Files = null;
public ObservableCollection<File> Files
{
get
{
if (_Files == null) _Files = GetFiles();
return _Files;
}
set
{
_Files = value;
}
}
}
Then bind the listbox to the selected treeview item.
<ListBox ItemsSource="{Binding ElementName=myTreeView, Path=SelectedItem.Files}"/>
You might have quite a number of files and folders so I think I would be inclined to lazy load as much as I could.
That means the viewmodel doesn't need to go iterate through the entire hard drive initially but you need some way of acting when selecteditem changes.
You can't bind selecteditem to a viewmodel because it's read only.
I would therefore use a behaviour like:
Data binding to SelectedItem in a WPF Treeview
Bind a SelectedFolder using that.
In the setter of SelectedFolder go get the list of folders and files for that folder and fill the two collections. One is the child collection of that selecteditem - for it's folders.
The other is an observableCollection for the files to see in the listbox.
Make that a propfull and implement inotifyproprtychanged so when I set it to a new collection it notifies the ui.
Bind that collection to the itemssource of the listbox.
Basicly The MVVM pattern uses three Layers :
The Model : Basicly it contains the Model classes and the business logic to get and manipulate Data information.
The ViewModel : It acts as an intermediate layer between the Model and the Views, it is attached to the different views.
The views : The différent views of the app.
Here an example how to fill a Window with list of Drives and Files.
Class BindableBaseViewModel
namespace TalkRepeater.ViewModel
{
public class BindableBaseViewModel : DependencyObject,INotifyPropertyChanged
{
protected virtual void SetProperty<T>(ref T member, T val,[CallerMemberName] string propertyName = null)
{
if (object.Equals(member, val)) return;
member = val;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
}
Class ViewModel
public class FoldersControlViewModel : BindableBaseViewModel
{
private ObservableCollection<Folders> _listFolders;
private ObservableCollection<Folders> _listFiles;
public FoldersControlViewModel()
{
FoldersBusinessObject vbo =new FoldersBusinessObject()
vbo.FillFolders();
ListFolders = FileBusinessObject.ListFolders;
}
public ObservableCollection<Folders> ListFolders
{
get
{
return _listFolders;
}
set
{
_listFolders = value;
OnPropertyChanged("ListFolders");
}
}
public ObservableCollection<Folders> ListFiles
{
get
{
return _listFiles;
}
set
{
_listFiles = value;
OnPropertyChanged("ListFiles");
}
}
Public void FillListFiles()
{
/*ListFiles= Cod to fill ListFiles*/
}
}
Class BusinessObject
public class FoldersBusinessObject
{
private ObservableCollection<Folders> _ListFolders;
public void FillFolders()
{
/* ListFolders= Code To fill the collection ListFolders */
}
public ObservableCollection<Folders> ListFolders
{
get
{
return _ListFolders;
}
set
{
_ListFolders = value;
}
}
}
Foldersview
<Window x:Class="Foldersview"
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"
d:DesignHeight = "300" Width="1007" Height="606">
<Grid Margin="10" >
<Canvas x:Name="canvasFolders" Margin="-10,0,912,10">
<TreeView x:Name="TreevFolders" ItemsSource="{Binding Path=ListFolders, Mode=TwoWay}" Canvas.Top="5" Canvas.Left="17" Width="142" Height="561"
SelectedItemChanged="TreevFolders_SelectedItemChanged" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ListFolders}">
<TextBlock Text="{Binding Path=FileName}">
</TextBlock>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Canvas>
<Canvas Margin="159,10,0,10">
<Listview x:Name="Listview1" ItemsSource="{Binding ListFiles, Mode=TwoWay}" >
</Listview>
</Canvas>
</Grid>
</Window>
Class Foldersview Code Behind
public partial class Foldersview : Window
{
private void TreevFolders_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
FoldersControlViewModel vmd = (FoldersControlViewModel)this.DataContext;
vmd.FillListFiles ();
}
}
Class Mainwindow
public class MainWindowViewModel : BindableBase
{
private FoldersControlViewModel FoldersviewModel;
public MainWindowViewModel()
{
FoldersviewModel = new FoldersControlViewModel();
Foldersview=new Foldersview();
Foldersview.Datacontext=FoldersviewModel;
}
}
Cordialy

Binding to Complex Objects in the ViewModel from the View?

Say for example I have the following type:
public class Site
{
public string Name { get; set; }
public int SiteId { get; set; }
public bool IsLocal { get; set; }
}
The above type can be assigned to be held in a Propety in a ViewModel like so assuming a corresponding backing field has been created but omitted here ofc:
public Site SelectedSite
{
get { return _selectedSite; }
set
{
_selectedSite = value;
// raise property changed etc
}
}
In my xaml a straight forward binding would be:
<TextBlock x:Name="StatusMessageTextBlock"
Width="Auto"
Height="Auto"
Style="{StaticResource StatusMessageboxTextStyle}"
Text="{Binding MessageToDisplay,
Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}" />
Can you extend a binding by using the dot notation syntax? e.g:
<TextBlock x:Name="StatusMessageTextBlock"
Width="Auto"
Height="Auto"
Style="{StaticResource StatusMessageboxTextStyle}"
**Text="{Binding SelectedSite.Name,**
Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}" />
Seems like a an interesting feature but my gut instinct is a no as my DC is being assigned at RunTime so at DesignTime or CompileTime, I can't see any clues that could make this feature work or not?
Correct me if have misunderstood what a complex object is, I have simplified mine down for the sake of this question.
Of course this is possible. However, WPF needs to know when any property along the path has changed. To that end, you need to implement INotifyPropertyChanged (or other supported mechanisms). In your example, both Site and the VM containing SelectedSite should implement change notification).
Here's how you could implement the functionality you specified in your question:
// simple DTO
public class Site
{
public string Name { get; set; }
public int SiteId { get; set; }
public bool IsLocal { get; set; }
}
// base class for view models
public abstract class ViewModel
{
// see http://kentb.blogspot.co.uk/2009/04/mvvm-infrastructure-viewmodel.html for an example
}
public class SiteViewModel : ViewModel
{
private readonly Site site;
public SiteViewModel(Site site)
{
this.site = site;
}
// this is what your view binds to
public string Name
{
get { return this.site.Name; }
set
{
if (this.site.Name != value)
{
this.site.Name = value;
this.OnPropertyChanged(() => this.Name);
}
}
}
// other properties
}
public class SitesViewModel : ViewModel
{
private readonly ICollection<SiteViewModel> sites;
private SiteViewModel selectedSite;
public SitesViewModel()
{
this.sites = ...;
}
public ICollection<SiteViewModel> Sites
{
get { return this.sites; }
}
public SiteViewModel SelectedSite
{
get { return this.selectedSite; }
set
{
if (this.selectedSite != value)
{
this.selectedSite = value;
this.OnPropertyChanged(() => this.SelectedSite);
}
}
}
}
And your view might look something like this (assuming a DataContext of type SitesViewModel):
<ListBox ItemsSource="{Binding Sites}" SelectedItem="{Binding SelectedSite}"/>
Below is what worked for me:
public Site SelectedSite
{
get { return _selectedSite; }
set
{
_selectedSite = value;
RaisePropertyChanged("SelectedSite");
}
}
In my xaml I was able to do:
<TextBox Name="tbSiteName"
Width="250"
Height="30"
Margin="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsReadOnly="True"
Style="{StaticResource MainTextBoxStyle}"
Text="{Binding SelectedSite.Name,
Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}" />
This allows you to access data members off the Site Type without having to create individual properties that wrap each data member on the Site Type. Then individual controls can bind to each property declared in the VM. In a one to one fashion, this aproach can become rather verbose. The binding extension attached to the Text property of the TextBox control shown above, shows that we are not binding to a simple straight forward property but actually to a custom type. Potentially removing the need to create more public properties.

Binding to individual elements in a collection

I am fairly new to MVVM, so bear with. I have a view model class that has a public property implemented as so:
public List<float> Length
{
get;
set;
}
In my XAML for the view, I have several text boxes, with each one bound to a specific element in this Length list:
<TextBox Text="{Binding Length[0], Converter=DimensionConverter}" />
<TextBox Text="{Binding Length[2], Converter=DimensionConverter}" />
<TextBox Text="{Binding Length[4], Converter=DimensionConverter}" />
The DimensionConverter is a IValueConverter derived class that formats the values like a dimension (i.e. 480.0 inches becomes 40'0" in the text box on screen), and back again (i.e. takes 35'0" for a string and yield 420.0 inches for the source)
My issue: I need to be able to validate each value in the List as it is changed in the associated TextBox. For some, I may need to modify other values in the List depending on the entered value (i.e. change the float at Length[0] will change the value at Length[4] and update the screen).
Is there any way to re-work the property to allow for an indexer? Or, do I need to create individual properties for each item in the List (which really makes the List unnecessary)? Essentially, since I already have the collection of float, I was hoping to be able to write MVVM code to validate each item as it is modified.
Thoughts? (and, thanks in advance)
You can use an ObservableCollection<float> instead of a List<float>, and handle the CollectionChanged event to detect when the user changes a value.
Wouldn't something like this:
<ItemsControl ItemsSource="{Binding Length}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Mode=TwoWay, Converter=DimensionConverter}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Be close to what you want?
It will display the entire list, and allow the user to modify the values, which will be returned straight back to the list, as long as your IValueConverter implements ConvertBack.
Then do as Thomas said to validate, or implement an ObservableLinkedList
What you do at the moment looks dirty already and it's barely a few lines of code..
It would be great if you can have a class which implements INotifyPropertyChanged to have the properties provided the length of list is constant.
if you want validate your text input with mvvm then create a model that you can youse at your viewmodel
public class FloatClass : INotifyPropertyChanged
{
private ICollection parentList;
public FloatClass(float initValue, ICollection pList) {
parentList = pList;
this.Value = initValue;
}
private float value;
public float Value {
get { return this.value; }
set {
if (!Equals(value, this.Value)) {
this.value = value;
this.RaiseOnPropertyChanged("Value");
}
}
}
private void RaiseOnPropertyChanged(string propName) {
var eh = this.PropertyChanged;
if (eh != null) {
eh(this, new PropertyChangedEventArgs(propName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
at your viewmodel you can use the model like this
public class FloatClassViewmModel : INotifyPropertyChanged
{
public FloatClassViewmModel() {
this.FloatClassCollection = new ObservableCollection<FloatClass>();
foreach (var floatValue in new[]{0f,1f,2f,3f}) {
this.FloatClassCollection.Add(new FloatClass(floatValue, this.FloatClassCollection));
}
}
private ObservableCollection<FloatClass> floatClassCollection;
public ObservableCollection<FloatClass> FloatClassCollection {
get { return this.floatClassCollection; }
set {
if (!Equals(value, this.FloatClassCollection)) {
this.floatClassCollection = value;
this.RaiseOnPropertyChanged("FloatClassCollection");
}
}
}
private void RaiseOnPropertyChanged(string propName) {
var eh = this.PropertyChanged;
if (eh != null) {
eh(this, new PropertyChangedEventArgs(propName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
here is the xaml example
<ItemsControl ItemsSource="{Binding Path=FloatClassViewmModel.FloatClassCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Value, Mode=TwoWay, Converter=DimensionConverter}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
hope this helps

WPF: Nested DependencyProperties

I have an ObservableCollection of "Layouts" and a "SelectedLocation" DependencyProperty on a Window. The SelectedLocation has a property called "Layout", which is an object containing fields like "Name" etc. I'm trying to bind a combobox to the SelectedLayout but it's not working.
The following does not work, I've tried binding to SelectedItem instead to no avail. I believe it may be something to do with the fact that I'm binding to a subProperty of the SelectedLocation DependencyProperty (though this does implement INotifyPropertyChanged.
<ComboBox Grid.Row="2" Grid.Column="0" x:Name="cboLayout" ItemsSource="{Binding Layouts,ElementName=root}" SelectedValue="{Binding SelectedLocation.Layout.LayoutID,ElementName=root}" DisplayMemberPath="{Binding Name}" SelectedValuePath="LayoutID" />
However, the following works (Also bound to the "SelectedLocation" DP:
<TextBox Grid.Row="4" Grid.Column="1" x:Name="txtName" Text="{Binding SelectedLocation.Name,ElementName=root,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
What type property Layouts has? I suppose something like this this: IEnumerable<Layout>.
But you bind selected value to Layout.LayoutID. So you got situation, when combo box contains Layout objects, and you try to select it by Int identifier. Of course binding engine can't find any Int there.
I have no idea about details of your code, so one thing I could propose: try to reduce your binding expression: SelectedItem="{Binding SelectedLocation.Layout,ElementName=root}.
If no success, provide more code to help me understand what's going on.
====UPDATE====
As I've said, you are obviously doing something wrong. But I am not paranormalist and couldn't guess the reason of your fail (without your code). If you don't want to share your code, I decided to provide simple example in order to demonstrate that everything works. Have a look at code shown below and tell me what is different in your application.
Class Layout which exposes property LayoutId:
public class Layout
{
public Layout(string id)
{
this.LayoutId = id;
}
public string LayoutId
{
get;
private set;
}
public override string ToString()
{
return string.Format("layout #{0}", this.LayoutId);
}
}
Class SelectionLocation which has nested property Layout:
public class SelectedLocation : INotifyPropertyChanged
{
private Layout _layout;
public Layout Layout
{
get
{
return this._layout;
}
set
{
this._layout = value;
this.OnPropertyChanged("Layout");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
var safeEvent = this.PropertyChanged;
if (safeEvent != null)
{
safeEvent(this, new PropertyChangedEventArgs(name));
}
}
}
And Window class with dependency properties (actually, in my example StartupView is UserControl, but it doesn't matter):
public partial class StartupView : UserControl
{
public StartupView()
{
InitializeComponent();
this.Layouts = new Layout[] { new Layout("AAA"), new Layout("BBB"), new Layout("CCC") };
this.SelectedLocation = new SelectedLocation();
this.SelectedLocation.Layout = this.Layouts.ElementAt(1);
}
public IEnumerable<Layout> Layouts
{
get
{
return (IEnumerable<Layout>)this.GetValue(StartupView.LayoutsProperty);
}
set
{
this.SetValue(StartupView.LayoutsProperty, value);
}
}
public static readonly DependencyProperty LayoutsProperty =
DependencyProperty.Register("Layouts",
typeof(IEnumerable<Layout>),
typeof(StartupView),
new FrameworkPropertyMetadata(null));
public SelectedLocation SelectedLocation
{
get
{
return (SelectedLocation)this.GetValue(StartupView.SelectedLocationProperty);
}
set
{
this.SetValue(StartupView.SelectedLocationProperty, value);
}
}
public static readonly DependencyProperty SelectedLocationProperty =
DependencyProperty.Register("SelectedLocation",
typeof(SelectedLocation),
typeof(StartupView),
new FrameworkPropertyMetadata(null));
}
XAML of StartupView:
<UserControl x:Class="Test.StartupView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:self="clr-namespace:HandyCopy"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="Root">
<WrapPanel>
<ComboBox ItemsSource="{Binding Path=Layouts,ElementName=Root}"
SelectedItem="{Binding Path=SelectedLocation.Layout, ElementName=Root}"/>
</WrapPanel>
</UserControl>

ObservableCollection<T> not updating UI

I'm having an issue with an ObservableCollection getting new items but not reflecting those changes in a ListView. I have enough quirks in the way I'm implementing this that I'm having a hard time determining what the problem is.
My ObservableCollection is implemented thusly:
public class MessageList : ObservableCollection<LobbyMessage>
{
public MessageList(): base()
{
Add(new LobbyMessage() { Name = "System", Message = "Welcome!" });
}
}
I store the collection in a static property (so that its easily accessible from multiple user controls):
static public MessageList LobbyMessages { get; set; }
In the OnLoad event of my main NavigationWindow I have the following line:
ChatHelper.LobbyMessages = new MessageList();
My XAML in the UserControl where the ListView is located reads as:
<ListBox IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Mode=OneWay}"
x:Name="ListBoxChatMessages"
d:UseSampleData="True"
ItemTemplate="{DynamicResource MessageListTemplate}"
IsEnabled="True">
<ListBox.DataContext>
<Magrathea_Words_Tools:MessageList/>
</ListBox.DataContext>
</ListBox>
The initial message that I added in the constructor appears in the UI just fine.
Now, the way I add new items to the collection is from a CallBack coming from a WCF service. I had this code working in a WinForms application and it was neccessary to marshall the callback to the UI thread so I left that code in place. Here is an abbreviated version of the method:
Helper.Context = SynchronizationContext.Current;
#region IServiceMessageCallback Members
/// <summary>
/// Callback handler for when the service has a message for
/// this client
/// </summary>
/// <param name="serviceMessage"></param>
public void OnReceivedServiceMessage(ServiceMessage serviceMessage)
{
// This is being called from the WCF service on it's own thread so
// we have to marshall the call back to this thread.
SendOrPostCallback callback = delegate
{
switch (serviceMessage.MessageType)
{
case MessageType.ChatMessage:
ChatHelper.LobbyMessages.Add(
new LobbyMessage()
{
Name = serviceMessage.OriginatingPlayer.Name,
Message = serviceMessage.Message
});
break;
default:
break;
}
};
Helper.Context.Post(callback, null);
}
While debugging I can see the collection getting updated with messages from the service but the UI is not reflecting those additions.
Any ideas about what I'm missing to get the ListView to reflect those new items in the collection?
I resolved this issue.
Neither the static property or the context of the incoming data had anything to do with the issue (which seems obvious in hindsight).
The XAML which was generated from Expression Blend was not up to the task for some reason. All I did to get this to work was assign the ItemSource to the collection in C#.
ListBoxChatMessages.ItemsSource = ChatHelper.LobbyMessages.Messages;
My XAML is now more simplified.
<ListBox IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Mode=OneWay}" Background="#FF1F1F1F"
Margin="223,18.084,15.957,67.787" x:Name="ListBoxChatMessages"
ItemTemplate="{DynamicResource MessageListTemplate}"
IsEnabled="True"/>
I'm a little confused as to why this works. I was reading the MSDN articles on how to bind data in WPF and they included several binding objects, referencing properties on object, etc. I don't understand why they went to all the trouble when one line of code in the UserControl's constructor does the trick just fine.
You need to make your poco class within the ObservableCollection implement INotifyPropertyChanged.
Example:
<viewModels:LocationsViewModel x:Key="viewModel" />
.
.
.
<ListView
DataContext="{StaticResource viewModel}"
ItemsSource="{Binding Locations}"
IsItemClickEnabled="True"
ItemClick="GroupSection_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="0,0,10,0" Style="{ThemeResource ListViewItemTextBlockStyle}" />
<TextBlock Text="{Binding Latitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="0,0,5,0"/>
<TextBlock Text="{Binding Longitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public class LocationViewModel : BaseViewModel
{
ObservableCollection<Location> _locations = new ObservableCollection<Location>();
public ObservableCollection<Location> Locations
{
get
{
return _locations;
}
set
{
if (_locations != value)
{
_locations = value;
OnNotifyPropertyChanged();
}
}
}
}
public class Location : BaseViewModel
{
int _locationId = 0;
public int LocationId
{
get
{
return _locationId;
}
set
{
if (_locationId != value)
{
_locationId = value;
OnNotifyPropertyChanged();
}
}
}
string _name = null;
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
OnNotifyPropertyChanged();
}
}
}
float _latitude = 0;
public float Latitude
{
get
{
return _latitude;
}
set
{
if (_latitude != value)
{
_latitude = value;
OnNotifyPropertyChanged();
}
}
}
float _longitude = 0;
public float Longitude
{
get
{
return _longitude;
}
set
{
if (_longitude != value)
{
_longitude = value;
OnNotifyPropertyChanged();
}
}
}
}
public class BaseViewModel : INotifyPropertyChanged
{
#region Events
public event PropertyChangedEventHandler PropertyChanged;
#endregion
protected void OnNotifyPropertyChanged([CallerMemberName] string memberName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(memberName));
}
}
}

Resources