WPF: What distinguishes a Dependency Property from a regular CLR Property? - wpf

In WPF, what, really, does it mean to be a "dependency property"?
I read Microsoft's Dependency Properties Overview, but it's not really sinking in for me. In part that article says:
Styles and templates are two of the chief motivating scenarios for using dependency properties. Styles are particularly useful for setting properties that define application user interface (UI). Styles are typically defined as resources in XAML. Styles interact with the property system because they typically contain "setters" for particular properties, as well as "triggers" that change a property value based on the real-time value for another property.
And then the example code is this:
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
....
<Button Style="{StaticResource GreenButtonStyle}">I am green!</Button>
But I'm not getting what is special about this. Does it just imply, that when I set Style on the button to the given style, that I am actually setting Background implicitly? Is that the crux of it?

Here's the explanation for how dependency properties work that I always wished someone had written for me. It's incomplete and quite possibly wrong, but it will help you develop enough of an understanding of them that you can will be able to grasp the documentation that you read.
Dependency properties are property-like values that are get and set via methods of the DependencyObject class. They can (and generally do) look very much like CLR properties, but they're not. And this gets to the first confusing thing about them. A dependency property is really made up of a couple of components.
Here's an example:
Document is a property of the RichTextBox object. It's a real CLR property. That is to say, it's got a name, a type, a getter, and a setter, just like any other CLR property. But unlike "normal" properties, the RichTextBox property doesn't merely get and set a private value inside the instance. Internally, it's implemented like this:
public FlowDocument Document
{
get { return (FlowDocument)GetValue(DocumentProperty); }
set { SetValue(DocumentProperty, value); }
}
When you set Document, the value you passed in gets passed to SetValue, along with DocumentProperty. And what is that? And how does GetValue get its value? And ...why?
First the what. There's a static property defined on the RichTextBox named DocumentProperty. When this property is declared, it's done like this:
public static DependencyProperty DocumentProperty = DependencyProperty.Register(
"Document",
typeof(FlowDocument),
typeof(RichTextBox));
The Register method, in this case, tells the dependency property system that RichTextBox - the type, not the instance - now has a dependency property named Document of type FlowDocument. This method stores this information...somewhere. Where, exactly, is an implementation detail that's hidden from us.
When the setter for the Document property calls SetValue, the SetValue method looks at the DocumentProperty argument, verifies that it's really a property that belongs to RichTextBox and that value is the right type, and then stores its new value...somewhere. The documentation for DependencyObject is coy on this implementation detail, because you don't really need to know it. In my mental model of how this stuff works, I assume there's a property of type Dictionary<DependencyProperty, object> that's private to the DependencyObject, so derived classes (like RichTextBox) can't see it but GetValue and SetValue can update it. But who knows, maybe it's written on parchment by monks.
At any rate, this value is now what's called a "local value," which is to say it's a value that's local to this specific RichTextBox, just like an ordinary property.
The point of all this is:
CLR code doesn't need to know that a property is a dependency property. It looks exactly like any other property. You can call GetValue and SetValue to get and set it, but unless you're doing something with the dependency property system, you probably don't need to.
Unlike a normal property, something other than the object that it belongs to can be involved in getting and setting it. (You could do this with reflection, conceivably, but reflection is slow. Looking things up in dictionaries is fast.)
This something - which is the dependency property system - essentially sits between an object and its dependency properties. And it can do all kinds of things.
What kinds of things? Well, let's look at some use cases.
Binding. When you bind to a property, it has to be a dependency property. This is because the Binding object doesn't actually set properties on the target, it calls SetValue on the target object.
Styles. When you set an object's dependency property to a new value, SetValue tells the style system that you've done so. That's how triggers work: they don't find out that a property's value has changed through magic, the dependency property system tells them.
Dynamic resources. If you write XAML like Background={DynamicResource MyBackground}, you can change the value of the MyBackground resource, and the background of the object referencing it gets updated. This isn't magic either; the dynamic resource calls SetValue.
Animations. Animations work by manipulating property values. Those have to be dependency properties, because the animation is calling SetValue to get at them.
Change notification. When you register a dependency property, you can also specify a function that SetValue will call when it sets the property's value.
Value inheritance. When you register a dependency property, you can specify that it participate in property value inheritance. When you call GetValue to get the value of an object's dependency property, GetValue looks to see if there's a local value. If there's not, it traverses up the chain of parent objects looking at their local values for that property.
This is how it is that you can set the FontFamily on a Window and magically (I'm using that word a lot) every control in the window uses the new font. Also, it's how it is that you can have hundreds of controls in a window without each of them having a FontFamily member variable to track their font (since they don't have local values) but you can still set the FontFamily on any one control (because of the seekrit hidden dictionary of values that every DependencyObject has).

In WPF, what, really, does it mean to be a "dependency property"?
In order to be a dependency property, the property must actually be defined as a DependencyProperty, statically, on the class. The dependency property system is very different than a standard CLR property.
Dependency properties are handled very differently, though. A type defines a dependency property statically, and provides a default value. The runtime actually doesn't generate a value for an instance until it's needed. This provides one benefit - the property doesn't exist until requested for a type, so you can have a large number of properties without overhead.
This is what makes the styling work property, but is also important to allow attached properties, property "inheritance" through the visual tree, and many other things WPF relies on.
For example, take the DataContext dependency property. Typically, you set the DataContext dependency property for a Window or a UserControl. All of the controls within that Window, by default, "inherit" their parent's DataContext proeprty automatically, which allows you to specify data bindings for controls. With a standard CLR property, you'd need to define that DataContext for every control in the window, just to get binding to work properly.

It may be helpful to understand what problem the dependency property is trying to solve.
If we put the Binding, Animation and the Change Event model to one side as they've been discussed in other answers, the benefit is memory usage and thus scalability to host many thousand WPF objects in a window.
If a window contains 1000 Label objects with each Label object having the usual Foreground, Background, FontFamily, FontSize, FontWeight, etc., then traditionally this would consume memory because each property would have a private backing field to store the value.
Most applications will change only a few properties, the majority of which will be left at their default values. Basically very wasteful and redundant information (each object just holding the same default values in memory)
This is where dependency properties are different.
// Lets register the Dependency Property with a default value of 20.5
public static readonly DependencyProperty ColumnWidthProperty =
DependencyProperty.Register("ColumnWidth", typeof(double), typeof(MyWPFControl), new UIPropertyMetadata(20.5, ColWitdhPropChanged));
public double ColumnWidth
{
get { return (double)GetValue(ColumnWidthProperty); }
set { SetValue(ColumnWidthProperty, value); }
}
There is no private backing field. When the dependency property is registered a default value can be specified. So in most cases the returned value from GetValue is the default value that has only been stored the once to cover all instances of the Label object across all windows of your application.
When a dependency property is set using the SetValue it stores the non-default value in a collection identified by the object instance, to be returned in all subsequent GetValue calls.
This storage method will therefore only consume memory for the properties of the WPF objects that have changed from the default value. i.e. only the differences from the default value.

A simple/fundamental difference - Change Notification: Changes to Dependency Properties are reflected/refreshed in UI on changes whereas CLR properties don't.
<Window x:Class="SampleWPF.MainWindow"
x:Name="MainForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleWPF"
Title="About WPF Unleashed" SizeToContent="WidthAndHeight"
Background="OrangeRed"
>
<StackPanel DataContext="{Binding ElementName=MainForm}">
<!-- Bind to Dependency Property -->
<Label Name="txtCount1" FontWeight="Bold" FontSize="20" Content="{Binding ElementName=MainForm, Path=Count1, Mode=OneWay}" />
<!-- Bind to CLR Property -->
<Label Name="txtCount2" Content="{Binding ElementName=MainForm, Path=Count2, Mode=OneWay}"></Label>
<!-- Bind to Dependency Property (Using DataContext declared in StackPanel) -->
<Label Name="txtCount3" FontWeight="Bold" FontSize="20" Content="{Binding Count1}" />
<!-- Child Control binding to Dependency Property (Which propagates down element tree) -->
<local:UserControl1 />
<!-- Child Control binding to CLR Property (Won't work as CLR properties don't propagate down element tree) -->
<local:UserControl2 />
<TextBox Text="{Binding ElementName=txtCount1, Path=Content}" ></TextBox>
<TextBox Text="{Binding ElementName=txtCount2, Path=Content}" ></TextBox>
<Button Name="btnButton1" Click="btnButton1_Click_1">Increment1</Button>
<Button Name="btnButton2" Click="btnButton1_Click_2">Increment2</Button>
</StackPanel>
</Window>
<UserControl x:Class="SampleWPF.UserControl1"
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">
<StackPanel>
<Label Content="{Binding Count1}" ></Label>
<!--
<Label Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Count1}"></Label>
-->
</StackPanel>
</UserControl>
<UserControl x:Class="SampleWPF.UserControl2"
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">
<StackPanel>
<Label Content="{Binding Count2}" ></Label>
<!--
<Label Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Count2}"></Label>
-->
</StackPanel>
</UserControl>
And the code behind here (To declare the CLR and Dependency property):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SampleWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static readonly DependencyProperty Count1Property;
private int _Count2 = 2;
public int Count2
{
get { return _Count2; }
set { _Count2 = value; }
}
public MainWindow()
{
return;
}
static MainWindow()
{
// Register the property
MainWindow.Count1Property =
DependencyProperty.Register("Count1",
typeof(int), typeof(MainWindow),
new FrameworkPropertyMetadata(1,
new PropertyChangedCallback(OnCount1Changed)));
}
// A .NET property wrapper (optional)
public int Count1
{
get { return (int)GetValue(MainWindow.Count1Property); }
set { SetValue(MainWindow.Count1Property, value); }
}
// A property changed callback (optional)
private static void OnCount1Changed(
DependencyObject o, DependencyPropertyChangedEventArgs e) {
}
private void btnButton1_Click_1(object sender, RoutedEventArgs e)
{
Count1++;
}
private void btnButton1_Click_2(object sender, RoutedEventArgs e)
{
Count2++;
}
}
}
Another feature provided by Dependency Properties is value inheritance - value set in top level elements propagates down the element tree - In following example taken from http://en.csharp-online.net, FontSize and FontStyle declared on "Window" tag is applied to all child elements underneath:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="About WPF Unleashed" SizeToContent="WidthAndHeight"
FontSize="30" FontStyle="Italic"
Background="OrangeRed">
<StackPanel>
<Label FontWeight="Bold" FontSize="20" Foreground="White">
WPF Unleashed (Version 3.0)
</Label>
<Label>© 2006 SAMS Publishing</Label>
<Label>Installed Chapters:</Label>
<ListBox>
<ListBoxItem>Chapter 1</ListBoxItem>
<ListBoxItem>Chapter 2</ListBoxItem>
</ListBox>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button MinWidth="75" Margin="10">Help</Button>
<Button MinWidth="75" Margin="10">OK</Button>
</StackPanel>
<StatusBar>You have successfully registered this product.</StatusBar>
</StackPanel>
</Window>
References:
http://www.codeproject.com/Articles/29054/WPF-Data-Binding-Part-1
http://en.csharp-online.net/WPF_Concepts%E2%80%94Property_Value_Inheritance

Related

Checkbox binding not working

I searched the forum and did everything as advised to create dependancy property and bind it to checkbox, but for some reason it doesn't bind.
<CheckBox IsChecked="{Binding ElementName=MainWindow, Path=isLoop}" Content="" Height="22" HorizontalAlignment="Left" Margin="250,208,0,0" x:Name="checkBox1" VerticalAlignment="Top" Width="22" />
C#
public bool isLoop
{
get { return (bool)GetValue(isLoopProperty); }
set { SetValue(isLoopProperty, value); }
}
public static readonly DependencyProperty isLoopProperty =
DependencyProperty.Register("isLoop", typeof(bool), typeof(MainWindow), new UIPropertyMetadata(true));
You've made some key mistakes in your sample.
First, you are not binding to an object that supports your "isLoop" property (unless "MainWindow" is a custom control that has that property). Somewhere in that CheckBox's hierarchy, you need to set the DataContext to an object that supports it, or bind to an element that has that property.
Second, you should rarely, if ever, create a dependency property in your business object. For business objects, follow the INotifyPropertyChanged pattern. Typically, you should create dependency properties in visual UI elements, such as custom controls in order to be able to bind data to them (a target, not the source).
So, to fix your problem, you should probably create an object that implements INotifyPropertyChanged, create an IsLoop property that throws the NotifyPropertyChanged event in the setter, and set this object as the DataContext to the CheckBox's parent container (or further up the hierarchy if appropriate).
HTH
You are binding to the Window itself. Do you mean to do that? Unless your code example is in the code behind then the binding will not work.
Since you're using an ElementName binding, I am guessing you are binding to a UI element. The problem is, none of the default UI elements come with a property called isLoop, so your binding is invalid.
There are a few things you can try.
If your isLoop property is part of the object named MainWindow's DataContext, change your binding to DataContext.isLoop
<CheckBox IsChecked="{Binding ElementName=MainWindow, Path=DataContext.isLoop}" ... />
If isLoop is actually a property on a custom class called MainWindow, such as your dependency property implies, verify that the object named MainWindow is actually of type MainWindow
<local:MainWindow x:Name="MainWindow" />
And if neither of those work, post your full XAML (particularly the part named MainWindow), the code for the class MainWindow, and the code that ties the MainWindow class object with the XAML UI.
The isLoop won't trigger when the checkbox is clicked. That is simply for accessing the depency property in code. You should add a PropertyCallback function and register that in the metadata.

Can a XAML object be a source for one binding as well as a target for another binding?

Is it possible to have a TextBlock as a target and a source?
Basically I have a bunch of entities which have simple relationships to other entities (like Entity1 Knows Entity3, Entity3 WorksAt Entity2 etc.)
I have a Link class that stores SourceEntity, Relationship and TargetEntity details.
What I want to be able to do is to select an entity then display the relationships related to that entity, with the target entities of each relationship listed underneath the relationship names.
When an entity is selected, an ObservableCollection is populated with the Links for that particular entity (SelectedEntityLinks<Link>).
Because each entity could have the same relationship to more than one target entity (Entity1 could know both Entity3 and Entity4 for eg.), I've created a method GetThisRelationshipEntities() that takes a relationship name as a parameter, looks through SelectedEntityLinks for relationship names that match the parameter, and returns an ObservableCollection with the target entities of that relationship.
In my xaml I have a WrapPanel to display each relationship name in a TextBlock:
<TextBlock x:Name="relationship" Text="{Binding Path=Relationship.Name}" />
Then underneath that another Textblock which should display the results of GetThisRelationshipEntities(String relationshipName).
So I want the "relationship" TextBlock to both get its Text from the binding I've shown above, but also to provide its Text as a parameter to the GetThisRelationshipEntities() method which I've added to <UserControl.Resources> as an ObjectDataProvider.
Sorry if this is a bit wordy but I hope it's clear. Any pointers/advice would be great.
To me it sounds like you should create a value converter class using IValueConverter and a property which is you relations table.
When doing
<TextBlock x:Name="relationship" Text="{Binding Path=Relationship.Name}" />
you would add
<TextBlock x:Name="relationship" Text="{Binding Path=Relationship.Name, Converter={StaticResource myRelationConverter}}" />
in the Convert() method you can do any crazy thing you want to.
I'm not entirely sure i got what you're trying to do, but i suggest trying to set the binding mode to TwoWay.
<TextBlock x:Name="relationship" Text="{Binding Path=Relationship.Name}"
Mode=TwoWay />
although now that i think about it, it might be the default option, so you can also try to call the GetThisRelationshipEntities() function on the TextBlock, every time it's source is updated:
private void relationship_SourceUpdated(object sender, DataTransferEventArgs e)
{
//To DO: whatever update you wanna make
}
Your wording is a litte inaccurate: it is not the DependencyObjects that are the source or target of a binding, but the properties of the DependencyObjects. A plain property can only be the source in a binding, but a DependencyProperty can act both as a source and as a target. For example in
<TextBox Text="{Binding Path=Name}" Name="txtName" />
<Label Content="{Binding ElementName=txtName, Path=Text}" />
the Text property of the TextBox is the target of the binding to some Name property in the DataContext, and at the same time it is the source of the binding to the Content property of the Label. The parameter of a method call is not a property, therefore it cannot be source or target in a binding. In your case the simplest solution is probably to handle the TextBlock.TextChanged event and to call your method from there. Using a ValueConverter as suggested by Martin is also an option.
Edit: Here is a working example that demonstrates the approach using the TextChanged event. It writes the contents of the TextBox to the Console everytime you change something. To bind to the result of your method you could just let the event handler write its result to a property and then bind to that property.
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"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Vertical">
<TextBox Name="textBox1" TextChanged="textBox1_TextChanged" />
</StackPanel>
</Window>
MainWindow.xaml.cs:
using System;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
Console.WriteLine(this.textBox1.Text);
}
}
}

Enable button based on TextBox value (WPF)

This is MVVM application. There is a window and related view model class.
There is TextBox, Button and ListBox on form. Button is bound to DelegateCommand that has CanExecute function. Idea is that user enters some data in text box, presses button and data is appended to list box.
I would like to enable command (and button) when user enters correct data in TextBox. Things work like this now:
CanExecute() method contains code that checks if data in property bound to text box is correct.
Text box is bound to property in view model
UpdateSourceTrigger is set to PropertyChanged and property in view model is updated after each key user presses.
Problem is that CanExecute() does not fire when user enters data in text box. It doesn't fire even when text box lose focus.
How could I make this work?
Edit:
Re Yanko's comment:
Delegate command is implemented in MVVM toolkit template and when you create new MVVM project, there is Delegate command in solution. As much as I saw in Prism videos this should be the same class (or at least very similar).
Here is XAML snippet:
...
<UserControl.Resources>
<views:CommandReference x:Key="AddObjectCommandReference"
Command="{Binding AddObjectCommand}" />
</UserControl.Resources>
...
<TextBox Text="{Binding ObjectName, UpdateSourceTrigger=PropertyChanged}"> </TextBox>
<Button Command="{StaticResource AddObjectCommandReference}">Add</Button>
...
View model:
// Property bound to textbox
public string ObjectName
{
get { return objectName; }
set {
objectName = value;
OnPropertyChanged("ObjectName");
}
}
// Command bound to button
public ICommand AddObjectCommand
{
get
{
if (addObjectCommand == null)
{
addObjectCommand = new DelegateCommand(AddObject, CanAddObject);
}
return addObjectCommand;
}
}
private void AddObject()
{
if (ObjectName == null || ObjectName.Length == 0)
return;
objectNames.AddSourceFile(ObjectName);
OnPropertyChanged("ObjectNames"); // refresh listbox
}
private bool CanAddObject()
{
return ObjectName != null && ObjectName.Length > 0;
}
As I wrote in the first part of question, following things work:
property setter for ObjectName is triggered on every keypress in textbox
if I put return true; in CanAddObject(), command is active (button to)
It looks to me that binding is correct.
Thing that I don't know is how to make CanExecute() fire in setter of ObjectName property from above code.
Re Ben's and Abe's answers:
CanExecuteChanged() is event handler and compiler complains:
The event
'System.Windows.Input.ICommand.CanExecuteChanged'
can only appear on the left hand side
of += or -=
there are only two more members of ICommand: Execute() and CanExecute()
Do you have some example that shows how can I make command call CanExecute().
I found command manager helper class in DelegateCommand.cs and I'll look into it, maybe there is some mechanism that could help.
Anyway, idea that in order to activate command based on user input, one needs to "nudge" command object in property setter code looks clumsy. It will introduce dependencies and one of big points of MVVM is reducing them.
Edit 2:
I tried to activate CanExecute by calling addObjectCommand.RaiseCanExecuteChanged() to ObjectName property setter from above code. This does not help either. CanExecute() is fired few times when form is initialized, but after that it never gets executed again. This is the code:
// Property bound to textbox
public string ObjectName
{
get { return objectName; }
set {
objectName = value;
addObjectCommand.RaiseCanExecuteChanged();
OnPropertyChanged("ObjectName");
}
}
Edit 3: Solution
As Yanko Yankov and JerKimball wrote, problem is static resource. When I changed button binding like Yanko suggested:
<Button Command="{Binding AddObjectCommand}">Add</Button>
things started to work immediately. I don't even need RaiseCanExecuteChanged(). Now CanExecute fires automatically.
Why did I use static resource in first place?
Original code was from WPF MVVM toolkit manual. Example in that manual defines commands as static resource and then binds it to menu item. Difference is that instead of string property in my example, MVVM manual works with ObservableCollection.
Edit 4: Final explanation
I finally got it. All I needed to do was to read comment in CommandReference class. It says:
/// <summary>
/// This class facilitates associating a key binding in XAML markup to a command
/// defined in a View Model by exposing a Command dependency property.
/// The class derives from Freezable to work around a limitation in WPF when
/// databinding from XAML.
/// </summary>
So, CommandReference is used for KeyBinding, it is not for binding in visual elements. In above code, command references defined in resources would work for KeyBinding, which I don't have on this user control.
Of course, sample code that came with WPF MVVM toolkit were correct, but I misread it and used CommandReference in visual elements binding.
This WPF MVVM really is tricky sometimes.
Things look much clearer now with the edits, thanks! This might be a stupid question (I'm somewhat tired of a long day's work), but why don't you bind to the command directly, instead of through a static resource?
<Button Command="{Binding AddObjectCommand}">Add</Button>
Since you are using the DelegateCommand, you can call it's RaiseCanExecuteChanged method when your text property changes. I'm not sure what you are trying to accomplish with your CommandReference resource, but typically you just bind the commands directly to the button element's Command property:
<TextBox Text="{Binding ObjectName, UpdateSourceTrigger=ValueChanged}" />
<Button Command="{Binding AddObjectCommand}" Content="Add" />
This would be the relevant portion of your view model:
public string ObjectName
{
get { return objectName; }
set
{
if (value == objectName) return;
value = objectName;
AddObjectCommand.RaiseCanExecuteChanged();
OnPropertyChanged("ObjectName");
}
}
Try raising CanExecuteChanged when your property changes. The command binding is really distinct from the property binding and buttons bound to commands are alerted to a change in status by the CanExecuteChanged event.
In your case, you could fire a check when you do the PropertyChanged on the bound property that would evaluate it and set the command's internal CanExecute flag and then raise CanExecuteChanged. More of a "push" into the ICommand object than a "pull".
Echoing Abe here, but the "right" path to take here is using:
public void RaiseCanExecuteChanged();
exposed on DelegateCommand. As far as dependencies go, I don't think you're really doing anything "bad" by raising this when the property that the command depends on changes within the ViewModel. In that case, the coupling is more or less contained wholly within the ViewModel.
So, taking your above example, in your setter for "ObjectName", you would call RaiseCanExecuteChanged on the command "AddObjectCommand".
I know this is an old question but I personally think it's easier to bind the textbox Length to button's IsEnabled property, e.g.:
<TextBox Name="txtbox" Width="100" Height="30"/>
<Button Content="SomeButton " Width="100" Height="30"
IsEnabled="{Binding ElementName=txtbox, Path=Text.Length, Mode=OneWay}"></Button>
If ElementName binding does not work, use:
<Entry x:Name="Number1" Text="{Binding Number1Text}" Keyboard="Numeric"></Entry>
<Entry x:Name="Number2" Text="{Binding Number2Text}" Keyboard="Numeric"></Entry>
<Button Text="Calculate" x:Name="btnCalculate" Command="{Binding CalculateCommand}" IsEnabled="{Binding Source={x:Reference Number1, Number2}, Path=Text.Length, Mode=OneWay}"></Button>
or use:
<Entry x:Name="Number1" Text="{Binding Number1Text}" Placeholder="Number 1" Keyboard="Numeric"></Entry>
<Entry x:Name="Number2" Text="{Binding Number2Text}" Placeholder="Number 2" Keyboard="Numeric"></Entry>
<Button VerticalOptions="Center" Text="Calculate" x:Name="btnCalculate" Command="{Binding CalculateCommand}">
<Button.Triggers>
<DataTrigger TargetType="Button"
Binding="{Binding Source={x:Reference Number1, Number2},
Path=Text.Length}"
Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Button.Triggers>

WPF Databinding CheckBox.IsChecked

How would I bind the IsChecked member of a CheckBox to a member variable in my form?
(I realize I can access it directly, but I am trying to learn about databinding and WPF)
Below is my failed attempt to get this working.
XAML:
<Window x:Class="MyProject.Form1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Title" Height="386" Width="563" WindowStyle="SingleBorderWindow">
<Grid>
<CheckBox Name="checkBoxShowPending"
TabIndex="2" Margin="0,12,30,0"
Checked="checkBoxShowPending_CheckedChanged"
Height="17" Width="92"
VerticalAlignment="Top" HorizontalAlignment="Right"
Content="Show Pending" IsChecked="{Binding ShowPending}">
</CheckBox>
</Grid>
</Window>
Code:
namespace MyProject
{
public partial class Form1 : Window
{
private ListViewColumnSorter lvwColumnSorter;
public bool? ShowPending
{
get { return this.showPending; }
set { this.showPending = value; }
}
private bool showPending = false;
private void checkBoxShowPending_CheckedChanged(object sender, EventArgs e)
{
//checking showPending.Value here. It's always false
}
}
}
<Window ... Name="MyWindow">
<Grid>
<CheckBox ... IsChecked="{Binding ElementName=MyWindow, Path=ShowPending}"/>
</Grid>
</Window>
Note i added a name to <Window>, and changed the binding in your CheckBox. You will need to implement ShowPending as a DependencyProperty as well if you want it to be able to update when changed.
Addendum to #Will's answer: this is what your DependencyProperty might look like (created using Dr. WPF's snippets):
#region ShowPending
/// <summary>
/// ShowPending Dependency Property
/// </summary>
public static readonly DependencyProperty ShowPendingProperty =
DependencyProperty.Register("ShowPending", typeof(bool), typeof(MainViewModel),
new FrameworkPropertyMetadata((bool)false));
/// <summary>
/// Gets or sets the ShowPending property. This dependency property
/// indicates ....
/// </summary>
public bool ShowPending
{
get { return (bool)GetValue(ShowPendingProperty); }
set { SetValue(ShowPendingProperty, value); }
}
#endregion
You must make your binding mode as TwoWay :
<Checkbox IsChecked="{Binding Path=ShowPending, Mode=TwoWay}"/>
If you have only one control that you want to bind to a property of your code-behind, then you can specify this as the source in your binding via a RelativeSource like this:
<CheckBox ...
IsChecked="{Binding ShowPending, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">
That could be the end of the answer. But more generally you will have multiple controls and wish to bind them to various properties on your class. In this case it is neater and more convenient to make use of the fact that the DataContext property (which is the default source object for data binding) is inherited down through the control hierarchy, so setting it at the top level will make it available to all the child controls.
There is no default value for DataContext, but there are at least two ways you can set the DataContext property of your Window element to point at itself:
By setting DataContext = this in the code-behind constructor. This is very simple, but some might argue that it's not clear in the XAML where the DataContext is pointing.
By setting the DataContext in XAML using DataBinding
The simplest and, I think, most elegant way to set the DataContext at the Window/UserControl level in XAML is very straight forward; just add DataContext="{Binding RelativeSource={RelativeSource Self}}" to your Window element. RelativeSource Self just means "bind directly to the object", which in this case is the Window object. The lack of a Path property results in the default Path, which is the source object itself (i.e. the Window).
<Window x:Class="MyProject.Form1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<CheckBox ...
IsChecked="{Binding ShowPending}">
</CheckBox>
</Grid>
</Window>
Once you have done this, the DataContext property for all child controls will be the Window class, so data binding to properties in your code-behind will be natural.
If for some reason you don't want to set the DataContext on the Window, but wish to set it lower down the control hierarchy, then you can do so by using the FindAncestor mechanism. E.g. if you want to set it on the Grid element and all children of the Grid:
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">
<CheckBox ...
IsChecked="{Binding ShowPending}">
</CheckBox>
</Grid>
It's probably worth noting at this point that what we have achieved so far is the ability to bind a UI Control to a property of your code-behind class, and for that code-behind property to be kept up-to-date with changes to the UI element. So if the user checks the CheckBox, the ShowPending property will be updated.
But quite often you also want the reverse to be true; a change to the source property should be reflected in a corresponding change to the UI Control. You can see this by adding another CheckBox control to your window, bound to the same ShowPending property. When you click one checkbox, you would probably hope or expect the other Checkbox to be synchronized, but it won't happen. To achieve this your code-behind class should either (a) implement INotifyPropertyChanged, (b) add a ShowPendingChanged event or (c) make ShowPending a Dependency Property. Of the 3, I suggest implementing INotifyPropertryChanged on your code-behind is the most common mechanism.

How to do simple Binding in Silverlight?

I understand that Silverlight 3.0 has binding but just want a simple example on how to use this to read a property from a class.
I have a class called Appointment which as a String property called Location:
Public Property Location() As String
Get
Return _Location
End Get
Set(ByVal Value As String)
_Location = Value
End Set
End Property
With a Private Declaration for the _Location as String of course.
I want a XAML element to bind to this property to display this in a TextElement, but it must be in XAML and not code, for example I want something like this:
<TextBlock Text="{Binding Appointment.Location}"/>
What do I need to do to get this to work?
It has to be a Silverlight 3.0 solution as some WPF features are not present such as DynamicResource which is what I'm used to using.
Just to add that my XAML is being loaded in from a seperate XAML File, this may be a factor in why the binding examples don't seem to work, as there are different XAML files the same Appointment.Location data needs to be applied.
You have two options.
If the "Appointment" class can be used as the DataContext for the control or Window, you can do:
<TextBlock Text="{Binding Location}" />
If, however, "Appointment" is a property of your current DataContext, you need a more complex path for the binding:
<TextBlock Text="{Binding Path=Appointment.Location}" />
Full details are documented in MSDN under the Binding Declarations page. If neither of these are working, make sure you have the DataContext set correctly.
You need something in code, unless you want to declare an instance of Appointment in a resource and bind to that but I doubt thats what you want.
You need to bind the Text property to the Property Path "Location" then assign the DataContext of the containing XAML to an instance of the Appointment:-
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding Location}" />
</Grid>
Then in the control's load event:-
void Page_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new Appointment() { Location = "SomePlace" };
}
Note in this case I'm using the default Page control.
If I'm reading correctly, you need to create an instance of Appointment, set the DataContext of the control to that instance and modify your binding to just say: Text="{Binding Location}"
Also, consider implementing INotifyPropertyChanged on your Appointment class to allow the data classes to notify the UI of property value changes.

Resources