I have Some UI logic and I need to Add them in Code behind. In order to overcome the code duplication, I need to use a property and change it. Normal MVVM thing. But when I try to do it with Codebehind. Mean I bind XAML with my code behind in order to access the isvisible function in several places. Problem is it does not binding or any other problem visibility did not change when action is fired.
My ContentView Xaml
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:customRenderes="clr-namespace:DipsDemoXaml.CustomRenderes;assembly=DipsDemoXaml"
x:Class="DipsDemoXaml.Views.Page1"
x:Name="navi">
<StackLayout BindingContext="{x:Reference Name=navi}">
<customRenderes:NavigationImageButton Source="MenuSettings"
x:Name="Button1"
Margin="0"
IsVisible="{Binding Visibility}"
/>
In code behind
public partial class Page1 : ContentView
{
private bool _expand;
private bool _visibility;
public bool Visibility
{
get => _visibility;
set
{
_visibility = value;
OnPropertyChanged();
}
}
public Page1 ()
{
InitializeComponent ();
}
private void Button1_OnItemTapped(object sender, EventArgs e)
{
if (_expand)
{
this.Hide();
}
else
{
this.Expand();
}
}
private async void Expand()
{
_expand = true;
Button5.Opacity = 1;
_visibility = true;
await Button5.RotateTo(180, 200);
}
private async void Hide()
{
_expand = false;
Button5.Opacity = 0.4;
_visibility = false;
await Button5.RotateTo(360, 200);
}
}
How to bind this in xamarin forms. Is my binding is wrong or where is the problem
my onpropertychanged method
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
changed?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Call Visibility, not _visibility , or manually trigger OnPropertyChanged. But the 1st option is preferred. BTW, I don't know what is your OnPropertyChanged implementation, but typically it is called with your property name, as #Maniax mentioned, or using nameof operator, e.g. OnPropertyChanged(nameof(Visibility))
First of all, PropetyChanged takes an argument,
OnPropertyChanged("Visibility");
I guess this should work but it is odd to put your ViewModel code in the code behind.
The idea of MVVM is to move the logic from to page, to the ViewModel, allowing you to manage the state of several pages within the same ViewModel with almost, if not, 0 code in the page behind the XAML.
So you probably should create another file that you will call ViewModel, and put you're business logic in it.
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:customRenderes="clr-
namespace:DipsDemoXaml.CustomRenderes;assembly=DipsDemoXaml"
x:Class="DipsDemoXaml.Views.Page1"
xmlns:vm="clr-namespace:DipsDemoXaml.ViewModels;assembly=DipsDemoXaml"
x:Class="DipsDemoXaml.Views.Page1"
x:Name="navi">
<ContentView.BindingContext>
<vm:MyViewModel/>
</ContentView.BindingContext>
<StackLayout>
<customRenderes:NavigationImageButton Source="MenuSettings"
x:Name="Button1"
Margin="0"
IsVisible="{Binding Visibility}"/>
And in MyViewModel.cs:
private bool _visibility;
public bool Visibility
{
get => _visibility;
set
{
_visibility = value;
OnPropertyChanged("Visibility");
}
}
So you can deal with any binding you want and use them easily in different pages.
I hope this helps.
Related
I have implemented something violating the MVVM pattern, and I wondered if there was a MVVM way of doing this.
I have a Window MainWindow, its DataContext is bound to a class called ViewModel which implements INotifyPropertyChanged.
I also implemented a Window ChildWindow which appears in a "Dialog" style when a button is clicked, using a RelayCommand. The DataContext of ChildWindow also binds to ViewModel. This Window is used to fill the details of a new list Item. I pass the View as a CommandParameter to the ViewModel, so that the ChildWindow can be centered in comparison to the MainWindow. This is not MVVM, and I would like to change this.
First, I implemented this in a non-MVVM way:
Here is my XAML for the button in MainWindow which opens the ChildWindow:
<Button Name="BtnInsert" Width="50" Margin="10" Command="{Binding OpenChildWindowCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">Add</Button>
Here is my simplified XAML for the ChildWindow:
<Window x:Class="HWE_Einteilen_Prototype.View.ListItemWindow"
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:HWE_Einteilen_Prototype.View"
mc:Ignorable="d"
Title="test" Height="400" Width="400">
<TextBox Width="50" Text="{Binding CurrentListItem.Id}" ></TextBox>
</Window>
And here is my (simplified) ViewModel Class:
public class ViewModel : INotifyPropertyChanged
{
private DataContext _ctx;
private ListItem _currentListItem;
private ObservableCollection<listItem> _listItems;
private ListItemWindow _listItemWindow;
private ICommand _openListItemWindowCommand;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<ListItem> ListItems
{
get { return _listItems; }
set
{
_listItems = value;
OnPropertyChanged();
}
}
public ListItem CurrentListItem
{
get { return _currentListItem; }
set
{
_currentListItem = value;
OnPropertyChanged();
}
}
public ICommand OpenListItemWindowCommand
{
get { return _openListItemWindowCommand; }
set
{
_openListItemWindowCommand = value;
OnPropertyChanged();
}
}
public ViewModel()
{
OpenListItemWindowCommand = new RelayCommand(this.OpenNewListItemWindow, this.CanOpenListItemWindow);
}
private void OpenNewListItemWindow(object parameter)
{
CurrentListItem = new listItem(){Id = "testId"};
_listItemWindow = new StListItemWindow(){DataContext = this};
_listItemWindow.Owner = (MainWindow)parameter;
_listItemWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
_listItemWindow.Closing += OnStListItemWindowClosing;
_listItemWindow.Show();
}
private bool CanOpenListItemWindow(object parameter)
{
return true;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
What I have tried:
I have tried implementing a Behavior (from system.windows.interactivity) for the button opening the child window, so that it creates a new Window and does all the centering and owner stuff, and leaving only CurrentListItem = new listItem(){Id = "testId"}; in the command method. However, in this case binding to CurrentListItem in the ChildWindow throws an exception.
XAML Code for the MainWindow Button:
<Button Name="BtnInsert" Width="50" Margin="10" Command="{Binding OpenListItemWindowCommand}" Content="Add">
<i:Interaction.Behaviors>
<behaviors:BehButtonNewWindow></behaviors:BehButtonNewWindow>
</i:Interaction.Behaviors>
</Button>
Behavior Code:
class BehButtonNewWindow : Behavior<Button>
{
private StListItemWindow _ListItemWindow;
protected override void OnAttached()
{
AssociatedObject.Click += OnClickHandler;
}
protected override void OnDetaching()
{
AssociatedObject.Click -= OnClickHandler;
}
private void OnClickHandler(object sender, RoutedEventArgs routedEventArgs)
{
if (sender is Button button)
{
var win = Window.GetWindow(button);
if (win != null)
{
_ListItemWindow = new ListItemWindow
{
DataContext = win.DataContext,
Owner = win,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
_ListItemWindow.Show();
}
}
}
}
Code of Command Execute Method from ViewModel:
private void OpenNewStListItemWindow(object parameter)
{
CurrentListItem = new ListItem(){Id = "testId"};
}
What am I doing wrong?
Credit for this answer goes to Will (see comments)
On handling the window opening:
Opening a window is a UI concern. Simply handle the button click in the codebehind, construct a new window and stick the current VM in it. MVVM != no codebehind.
On handling vm code:
[...] If you mean that last little bit of code at the bottom, make it public and have the window call it before opening the new window. The UI is perfectly fine knowing about your view models. They're designed to display their state and bind to their properties.
Thanks for your help!
I have a TextBlock control inside a HubSection in a Windows 8.1 Universal app.
<TextBlock x:Name="api_enabled_label"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Text="{Binding APIinfotext}" />
Now when the page is launched, in the contrustor, there is a method that is run.
public string APIinfotext { get; set; }
public sealed partial class MainPage : Page {
VoipMS voip_service = new VoipMS("shoukatali#hotmail.com", "Kitt0cat");
public string APIinfotext { get; set; }
public MainPage() {
this.InitializeComponent();
// disable sections until API is enabled
mainpagehub.Sections[1].IsEnabled = false;
mainpagehub.Sections[2].IsEnabled = false;
//check for API and enable sections
checkAPI();
}
private async void checkAPI() {
//irrelevant code above
switch (result) {
case "success":
APIinfotext = "Your API is connected";
break;
//irrelevant code below
}
}
So why dosnt this work? I set the DataContext of the Textblock to the current class (which is the MainPage partial class) and the property is a public property.
Note: Today is my first time working with .net 4.5 with XAML after a huge break at the .net 2.0 framework with WinForms.
Your binding doesn't know that APIinfotext property has changed. To let the bindings know that the property has changed you can do one of the following. The first one is the easiest.
1) implement INotifyPropertyChanged interface and raise the PropertyChanged changed event once APIinfotext has changed (PropertyChanged("APIinfotext"));
2) Have an event called APIinfotextChanged with the standard event signature and raise that event after the property has changed.
3) Implement your property as a DependencyProperty (not an ideal solution in this case).
You might be missing the part where you have to RaiseProperyChange NotifyPropertyChage to update the bindings. your Model should implement the INotifyPropertyChanged interface
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
then
RaisePropertyChanged("APIinfotext");
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.propertychanged.aspx
Looks like you need a very simple example of what the other two are talking about. Let's assume nothing. You need to set the DataContext correctly, plus raise the event. This is as simple as I can put it, when you click on the button it will change the TextBox because I change the Property which raises the event.
XAML
<Page>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<TextBox Text="{Binding APIinfotext}" Height="100" Width="400" HorizontalAlignment="Left"/>
<Button x:Name="myButton" Content="Change Text" Height="200" Width="400" Click="myButton_Click"/>
</StackPanel>
</Grid>
</Page>
C# (Pay attention, to the SET part of the APIinfotext)
using System.ComponentModel; // INotifyPropertyChanged
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private string _apiinfotext = "Default Text";
public string APIinfotext
{
get { return _apiinfotext; }
set
{
_apiinfotext = value;
RaisePropertyChanged("APIinfotext");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
this.APIinfotext = "Don't confuse movement for progress.";
}
}
I 'm having problem with TextBlock/TextBox binding. The TextBlock doesn't display the property's content. When I 'm debugging my app, property has content. How you can do it?
Xaml.
<TextBlock HorizontalAlignment="Left" Margin="730,191,0,0" TextWrapping="Wrap" Text="{Binding XmlContentFile, Mode=TwoWay}" VerticalAlignment="Top" Height="429" Width="465"/>
I was finding simple code in web, but I didn't find code.
Code property
public string XmlContentFile
{
get
{
return this.xmlContentFile;
}
set
{
this.xmlContentFile = value;
}
}
My DataContext
DataContext="{Binding Main, Source={StaticResource Locator}}">
Method load XML file to string variable
public async void XmlContentLoad()
{
if (selectFile != null)
{
try
{
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await storageFolder.GetFileAsync(selectFile);
xmlFileTextContent = await FileIO.ReadTextAsync(storageFile);
}
catch (Exception)
{
throw new Exception("Bug");
}
}
}
The problem is that your XmlContentFile property doesn't raise any notifications when it's changed. Your ViewModel needs to implement INotifyPropertyChanged and raise an event whenever any property has changed.
It's likely that your view and its data bindings are getting setup and executed before XmlContentLoad completes (it's asynchronous). If the binding has already completed before the data is loaded, the only way the binding will happen again is if the property raises a notification that it has changed.
It's also worth pointing out that in your XmlContentLoad method you're setting the private variable and not the public property.
xmlFileTextContent = await FileIO.ReadTextAsync(storageFile);
Setting the private variable will never raise property change notification even if you have the setter code wired up to raise the notification. You'll either need to change XmlContentLoad to set the property and have the OnPropertyChanged notification in the setter (recommended) or you'll need to call OnPropertyChanged after you set the private variable (not recommended).
Hope that helps.
Dev support, design support and more awesome goodness on the way: http://bit.ly/winappsupport
Make sure you are setting the Binding Source correctly :
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded_1" >
<Grid>
<TextBlock Text="{Binding XmlContentFile, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="#FFF3A3A3"/>
</Grid>
and make sure as well you are setting the value of your property in the right place :
public partial class MainWindow : Window,INotifyPropertyChanged
{
private string _xmlContentFile;
public string XmlContentFile
{
get
{
return _xmlContentFile ;
}
set
{
_xmlContentFile = value;
OnPropertyChanged("XmlContentFile");
}
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
XmlContentFile = "New Value !";
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
True that this answer is not in MVVM, but that won't need much changings except that you will be needing to set your DataContext to your ViewModel.
My main page has the appbar and it is shared across different pages. I wrote the following code to open the appbar on the click of a gridview item.
XAML
<AppBar Opened="AppBar_Opened" IsOpen="{Binding IsAppBarOpen}">
Back end
private void Clock_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
App.ViewModel.SelectedClock = (Clock)ThemeGridView.SelectedItem;
App.WorldViewModel.IsAppBarOpen = true;
}
private void ThemeGridView_ItemClick(object sender, ItemClickEventArgs e)
{
App.ViewModel.SelectedClock = (Clock)ThemeGridView.SelectedItem;
App.WorldViewModel.IsAppBarOpen = true;
}
WorldViewModel
private bool _IsAppBarOpen;
public bool IsAppBarOpen
{
get { return _IsAppBarOpen; }
set { base.SetProperty(ref _IsAppBarOpen, value); }
}
GridView XAML
<GridView
Grid.Row="1"
Grid.Column="1"
x:Name="ThemeGridView"
ItemsSource="{Binding Clocks}"
ItemTemplate="{StaticResource WorldClockTemplate}"
SelectionChanged="Clock_SelectionChanged"
SelectionMode="None"
IsItemClickEnabled="True"
ItemClick="ThemeGridView_ItemClick"
>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
But the appbar is not popping up when i select the gridview item. There is no binding error so its really mysterious!
There is not way to bind IsOpen property according the msdn:
Note Binding to the IsOpen property doesn't have the expected results
because the PropertyChanged notification doesn't occur when the
property is set.
<AppBar Opened="AppBar_Opened" IsOpen="{Binding IsAppBarOpen, **Mode=TwoWay**}">
This works for me. I use MVVM Light Toolkit.
public bool AppBarIsOpen
{
get { return this._appBarIsOpen; }
set
{
if (this._appBarIsOpen == value) { return; }
this._appBarIsOpen = value;
this.RaisePropertyChanged("AppBarIsOpen"); // without INotifyPropertyChanged it doesn't work
}
}
<AppBar
IsSticky="True"
IsOpen="{Binding Path=AppBarIsOpen, Mode=TwoWay}">
Roman Weisert's answer correctly states the likely reason for it not working, although you also must make the binding two-way as Zack Weiner suggested (I'm not sure the reason for the latter since the binding is not working in the target-to-source direction anyway). The current value of AppBar.IsOpen may not be reflected by IsAppBarOpen of your view-model. When that's the case, and you try updating the value, it's possible that no PropertyChanged event is raised since you may not actually be updating a value. Instead, you may be just setting the value from false to false or from true to true. Most SetProperty method implementations do not raise the PropertyChanged event unless there is an actual change, and I presume yours is the same.
To fix the problem, consider modifying your view-model as follows:
public bool IsAppBarOpen
{
get { return _IsAppBarOpen; } //changes initiated from UI not reflected
set //not updated from UI
{
_IsAppBarOpen = value;
base.OnPropertyChanged();
}
}
bool _IsAppBarOpen;
The notable difference from your view-model's code, is that SetProperty is not called here so PropertyChanged is raised even when the backing store equals the newly introduced value. In case your base class differs, note that mine has an OnPropertyChanged method with the signature
void OnPropertyChanged( [CallerMemberName] string propertyName = null )
that serves to raise the PropertyChanged event.
I can see from your use of the code-behind, though, that you are not really following MVVM. If MVVM is not a concern to you, then you could forgo the IsAppBarOpen property altogether and just directly set AppBar.IsOpen. As someone who religiously adheres to MVVM, however, I do not recommend that you further head in that (sinful) direction.
I had the same issue and using Caliburn Micro for WinRT and with this code worked for me:
<AppBar IsOpen="{Binding AppBarsOpen}" Name="MainAppBar" Padding="10,0,10,0" AutomationProperties.Name="Bottom App Bar">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<StackPanel x:Name="LeftPanel" Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left">
<Button Name="ShowFlyout" Style="{StaticResource BookmarksAppBarButtonStyle}" />
</StackPanel>
<StackPanel x:Name="RightPanel" Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right">
<Button Style="{StaticResource SaveAppBarButtonStyle}" />
</StackPanel>
</Grid>
</AppBar>
And that's your property in ViewModel:
public bool AppBarsOpen
{
get { return _appBarsOpen; }
set
{
if (value.Equals(_appBarsOpen)) return;
_appBarsOpen = value;
NotifyOfPropertyChange(() => AppBarsOpen);
}
}
Had the same issue, solved it by adding the Closed event and updating the ViewModel from the code behind. Saw no other way since TwoWay binding was not working as Roman pointed out.
XAML
<AppBar x:Name="BottomAppBar1"
AutomationProperties.Name="Bottom App Bar"
Closed="BottomAppBar1_Closed"
IsOpen="{Binding IsOpen, Mode=TwoWay}"
IsSticky="True">
C# Code behind
private void BottomAppBar1_Closed(object sender, object e)
{
MainViewModel vm = this.DataContext as MainViewModel;
vm.IsOpen = false;
}
C# MainViewModel
public const string IsOpenPropertyName = "IsOpen";
private bool isOpen = false;
/// <summary>
/// Sets and gets the IsOpen property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public bool IsOpen
{
get
{
return isOpen;
}
set
{
RaisePropertyChanging(IsOpenPropertyName);
isOpen = value;
RaisePropertyChanged(IsOpenPropertyName);
}
}
You should bind both IsOpen and IsSticky two way because otherwise you will get problems with for example having to tap two time to unselect an item (once to close the app bar and once for unselecting) and also it's the will help having your app bar behave more standarly (will prevent the app bar to pop down on tap when an item is selected).
To show the app bar you will need to do the following (the order is important):
this.IsAppBarSticky = true;
this.IsAppBarOpen = true;
and to hide it, do the following:
this.IsAppBarSticky = false;
this.IsAppBarOpen = false;
Another way to make this work without having to use a codebehind handler for app bar closed event:
public class AppBarClosedCommand
{
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand),
typeof(AppBarClosedCommand), new PropertyMetadata(null, CommandPropertyChanged));
public static void SetCommand(DependencyObject attached, ICommand value)
{
attached.SetValue(CommandProperty, value);
}
public static ICommand GetCommand(DependencyObject attached)
{
return (ICommand)attached.GetValue(CommandProperty);
}
private static void CommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Attach click handler
(d as AppBar).Closed += AppBar_onClose;
}
private static void AppBar_onClose(object sender, object e)
{
// Get GridView
var appBar = (sender as AppBar);
// Get command
ICommand command = GetCommand(appBar);
// Execute command
command.Execute(e);
}
}
then in the XAML you can use it like :
common:AppBarClosedCommand.Command="{Binding AppBarClosedCommand}"
with the command function looking like:
public void OnAppBarClosed()
{
AppBarOpen = false;
}
I have created blank C#/XAML Windows 8 application. Add simple XAML code:
<Page
x:Class="Blank.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel
Margin="0,150"
HorizontalAlignment="Center">
<TextBlock
x:Name="xTitle"
Text="{Binding Title, Mode=TwoWay}"/>
<Button Content="Click me!" Click="OnClick" />
</StackPanel>
</Grid>
</Page>
And the simple code in C# part:
public sealed partial class MainPage
{
private readonly ViewModel m_viewModel;
public MainPage()
{
InitializeComponent();
m_viewModel = new ViewModel
{
Title = "Test1"
};
DataContext = m_viewModel;
}
private void OnClick(object sender, RoutedEventArgs e)
{
m_viewModel.Title = "Test2";
}
}
Now I want to implement ViewModel. I have two way:
Use Dependency Property
Implement INotifyPropertyChanged
For first approach it is:
public class ViewModel : DependencyObject
{
public string Title
{
get
{
return (string)GetValue(TitleProperty);
}
set
{
SetValue(TitleProperty, value);
}
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string)
, typeof(ViewModel)
, new PropertyMetadata(string.Empty));
}
For second it is:
public class ViewModel : INotifyPropertyChanged
{
private string m_title;
public string Title
{
get
{
return m_title;
}
set
{
m_title = value;
OnPropertyChanged("Title");
}
}
protected void OnPropertyChanged(string name)
{
if (null != PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
I prefer the first way, because it allows use coerce (Silverlight for web and for WP7 doesn't have coerce functionality.. WinRT too.. but I'm still looking and hope) and looks more natural for me. But unfortunately, it works as OneTime for the first approach.
Could anybody explain to me why MS abandon using Dependency Property for implementing view model?
You should not be using a DependencyProperty in your ViewModel - you should only use them in your controls. You will never want to bind one ViewModel to another, also ViewModels do not need to persist their values nor provide default values, nor provide property metadata.
You should only use INotifyPropertyChanged in your ViewModels.