I am trying to bind a device object List to a costume control i am working on. I getting this error.
A 'Binding' cannot be set on the 'Devices' property of type
'CamaraSelection'. A 'Binding' can only be set on a DependencyProperty
of a DependencyObject.
xml code
<trainControl:CamaraSelection Devices="{Binding DeviceList}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
Control Code
private List<Device> devices = new List<Device>();
public static readonly DependencyProperty DeviceListProperty =
DependencyProperty.Register("DeviceList", typeof(List<Device>), typeof(CamaraSelection),
new PropertyMetadata(default(ItemCollection), OnDeviceListChanged));
private static void OnDeviceListChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var camaraSelection = dependencyObject as CamaraSelection;
if (camaraSelection != null)
{
camaraSelection.OnDeviceListChanged(dependencyPropertyChangedEventArgs);
}
}
private void OnDeviceListChanged(DependencyPropertyChangedEventArgs e)
{
}
public List<Device> Devices
{
get { return (List<Device>)GetValue(DeviceListProperty); }
set { SetValue(DeviceListProperty, value); }
}
The property where the binding is set on has to be a DependencyProperty. In your case it's the Devices-property. The first argument in the DependencyProperty.Register() method has to be the name of your property. The first argument in your code is "DeviceList" but your Property's name is Devices.
public static readonly DependencyProperty DevicesProperty =
DependencyProperty.Register("Devices", typeof(List<Device>), typeof(CamaraSelection),
new PropertyMetadata(default(ItemCollection), OnDeviceListChanged));
public List<Device> Devices
{
get { return (List<Device>)GetValue(DevicesProperty ); }
set { SetValue(DevicesProperty, value); }
}
"Devices" Property in your class must be a dependency property not the "DeviceList". The property which you are binding to must be a dependency property.
Related
I have the following class:
public class dm_fourvalues : DependencyObject
{
[JsonProperty]
public double First
{
get { return (double)GetValue(FirstProperty); }
set
{
SetValue(FirstProperty, value);
}
}
public static readonly DependencyProperty FirstProperty =
DependencyProperty.Register("First", typeof(double), typeof(dm_fourvalues),
new FrameworkPropertyMetadata(1d,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnFirstPropertyChanged)));
private static void OnFirstPropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
dm_fourvalues uci = sender as dm_fourvalues;
if (uci != null)
{
uci.OnFirstChanged();
}
}
private void OnFirstChanged()
{
Console.WriteLine("first on dm fourvalues changed");
}
Now if use this class as identical property on another object, when the First property gets changed,
this object's OnChanged is not triggered, thus also a binding would not work.
What defines that a parent dependencyobject has been changed?
I have created a custom user control that is basically built of a grid, an image, and a textblock. I want to be able to set the source of the image and the text of the text block from properties of the user control. I have set up the following dependency properties; however, I want to know if there is a better way to set the child element's properties than the way below.
public sealed partial class LabeledTile : UserControl
{
public LabeledTile()
{
InitializeComponent();
}
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(LabeledTile), new PropertyMetadata(null,(o, args) => ((LabeledTile) o).ImageSourceChanged((ImageSource)args.NewValue)));
private void ImageSourceChanged(ImageSource newValue)
{
ImageElement.Source = newValue;
}
public ImageSource ImageSource
{
get { return (ImageSource) GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(String), typeof(LabeledTile), new PropertyMetadata(null, (o, args) => ((LabeledTile)o).TextChanged((String)args.NewValue)));
private void TextChanged(string newValue)
{
TextElement.Text = newValue;
}
public String Text
{
get { return (String) GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
This is my first time using a dependency property and I want to make sure I am on the track. It seems like more work than should be required. Also, are callbacks really the best way to set the value?
Thank you in advance for the help.
In developing some UserControls for internal use I followed this exmaple from MSDN http://msdn.microsoft.com/en-us/library/vstudio/ee712573(v=vs.100).aspx
The public value of one control is used by another control. The way I have this working currently is hooking into an event that is fired in the first control through code-behind. I am thinking that making one or both of the properties DependencyProperties which would eliminate the need for the code-behind.
public partial class UserControl1 : UserControl
{
private DataModel1 dm;
public UserControl1()
{
this.DataContext = new DataModel1();
dm = (DataModel1)DataContext;
InitializeComponent();
}
public DataValue CurrentValue
{
get { return dm.CurrentValue; }
set { dm.CurrentValue = value; }
}
}
public class DataModel1 : INotifyPropertyChanged
{
private DataValue _myData = new DataValue();
public DataValue CurrentValue
{
get { return _myData; }
set { if (_myData != value) {_myData = value OnPropertyChanged("CurrentValue"); }
}
// INotifyPropertyChanged Section....
}
The property is just a pass through from the DataModel1 class.
Both UserControls are very similar in their structure and have the same public properties. I would like to replace the code behind eventhandler with a Binding similar, I think to:
<my:UserControl1 Name="UserControl1" />
<my:UserControl2 CurrentValue={Binding ElementName="UserControl1", Path="CurrentValue"} />
but the standard examples of DependencyProperties have getters and setter that use the GetValue and SetValue functions which use a generated backing object instead of allowing a pass through.
public DataValue CurrentValue
{
get { return (DataValue)GetValue(CurrentValueProperty); }
set { SetValue(CurrentValueProperty, value); }
}
I think the DP should look like:
public static readonly DependencyProperty CurrentValueProperty =
DependencyProperty.Register("CurrentValue", typeof(DataValue), typeof(UserControl1));
How can I change the definition of the public backing property to support the databinding pass through?
I found that jumping into the OnPropertyChanged event allowed me to pass the data through to the DataModel1. I am not 100% sure that this is the correct answer but it gets the job done.
Here is the corrected code:
public static readonly DependencyProperty CurrentValueProperty =
DependencyProperty.Register("CurrentValue", typeof(DataValue), typeof(UserControl1),
new PropertyMetadata(new PropertyChangedCallback(OnCurrenValueChanged)));
private static void OnCurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UserControl1 uc = d as UserControl1;
if (e.NewValue != null)
{
uc.dm.CurrentValue = e.NewValue as DataValue;
}
}
public DataValue CurrentValue
{
get { return GetValue(CurrentValueProperty) as DataValue; }
set { SetValue(CurrentValueProperty, value); }
}
I am working on a WPF project. And I just created a dependency property. This dependency property is intended to make the RichTextBox.Selection.Text property bindeable.
But what I cannot do is get and set data to RichTextBox.Selection.Text using the same DP.
This is the code that I used if I ONLY want to get data from my RichTextBox.Selection.Text using binding:
public class MyRichTextBox: RichTextBox
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(MyRichTextBox),
new PropertyMetadata(
TextPropertyCallback));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public MyRichTextBox()
{
this.TextChanged += new TextChangedEventHandler(MyRichTextBox_TextChanged);
}
void MyRichTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
Text = this.Selection.Text;
}
And it works perfectly, but with this code I cannot send any data from my ViewModel class.
So, if I ONLY want to set data to the RichTextBox.Selection.Text property from my ViewModel I used this code:
public class MyRichTextBox: RichTextBox
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(MyRichTextBox),
new PropertyMetadata(
TextPropertyCallback));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
private static void TextPropertyCallback(DependencyObject controlInstance, DependencyPropertyChangedEventArgs args)
{
MyRichTextBox instance = (MyRichTextBox)controlInstance;
instance.Selection.Text = (String)args.NewValue;
}
So, What Can I do if I want to be able to get and set data using the same dependency property???
Hope someone can help me, tahnk you in advance
Instead of binding your input control's text to the VM's property, you have binded an attached property to it, and in that attached property's value changed you set the input control's text.
In other words - there is nothing monitoring the changed to the input control's text.
Edit:
You are still doing:
instance.Selection.Text = (String)args.NewValue;
However, there is no notification of change to instance.Selection.Text.
I made own dependency property like this
public bool Visible
{
get
{
return (bool)GetValue(VisibleProperty);
}
set
{
System.Windows.Visibility v = value == true ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
SetValue(VisibleProperty, value);
border.Visibility = v;
}
}
public static readonly DependencyProperty VisibleProperty = DependencyProperty.Register("Visible", typeof(bool), typeof(SpecialMenuItem), new UIPropertyMetadata(false));
I'm binding my app property to it, but no luck.
App property(app.xaml.cs) and binding:
public bool IsGamePlaying
{
get
{
return isGamePlaying;
}
set
{
isGamePlaying = value;
}
}
private bool isGamePlaying;
<my:SpecialMenuItem ... Visible="{Binding Path=IsGamePlaying, Source={x:Static Application.Current}}" />
When I'm in debug, it reads the IsGamePlaying property, but doesn't make attempt to set the Visible property
How make it work?
You cannot include any logic in your dependency property wrapper. WPF will, where possible, directly call GetValue/SetValue rather than use your CLR property. You should include any extraneous logic by using metadata in your dependency property. For example:
public static readonly DependencyProperty VisibleProperty = DependencyProperty.Register("Visible", typeof(bool), typeof(SpecialMenuItem), new FrameworkPropertyMetadata(false, OnVisibleChanged));
private static void OnVisibleChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
// logic here will be called whenever the Visible property changes
}
The CLR wrapper is merely a convenience for consumers of your class.