How Set And Get data using the same Dependency Property? - c#

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.

Related

How to update one dependency property from another in UWP

I have two dependency properties and when value in First changes, I would like to update also the Second - for example give it temporary value and update UI, but I don't want to break the binding on Second property.
public bool Frist
{
get { return (bool)GetValue(FristProperty); }
set { SetValue(FristProperty, value); }
}
public static readonly DependencyProperty FristProperty =
DependencyProperty.Register("Frist", typeof(bool), typeof(ItemControl), new PropertyMetadata(false, FirstUpdated));
private static void FirstUpdated(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var theControl = d as ItemsControl;
// I would like to update also second dependency property here
// for example if First == true, then Second = Overriden
// else Second = the value from binding
}
public string Second
{
get { return (string)GetValue(SecondProperty); }
set { SetValue(SecondProperty, value); }
}
public static readonly DependencyProperty SecondProperty =
DependencyProperty.Register("Second", typeof(string), typeof(ItemsControl), new PropertyMetadata(string.Empty));
I've taken a look at various samples from WPF, but seems like there are missing things in UWP. What are the options?

Changing the value of a DependencyProperty inside its PropertyChangedCallback doesn't update the binding source

I have some C# code of the following form:
class FooBehavior : Behavior<Foo>
{
public static readonly DependencyProperty FooPropProperty = DependencyProperty.Register("FooProp", typeof(string), typeof(FooBehavior),
new FrameworkPropertyMetadata(FooPropProperty_Changed)
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
public String FooProp { get { return (string)GetValue(FooPropProperty); } set { SetValue(FooPropProperty, value); } }
private static void FooPropProperty_Changed(object sender, DependencyPropertyChangedEventArgs args)
{
/* re-entrancy check done here*/
// ...
if (/* args.NewValue is something bad that I can't use */)
FooProp = (string)args.OldValue;
try
{
/* do stuff here that might throw */
}
catch
{
FooProp = /* some known good value */;
throw;
}
}
}
I've taken out most of the actual code, but this shows the basics. What is happening is that I have a DependencyProperty where I want to to do validation on the property change, but I can't do it via the normal ValidateValueCallback method. I'd like to set the DependencyProperty back to its original value or to a known good value and have that change propagate to the viewmodel property to which the DependencyProperty is bound.
The problem I have is that when I get a value that I can't use, I can change the DependencyProperty's value, but the viewmodel doesn't see this new value. How can I get the value to propagate back to the viewmodel?

Setting a custom control's member's property using a dependency property

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.

WFP Binding List oc Object to a Custume Control

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.

How to bind a dependency property for a custom control to its view models property

I am trying to bind a custom control's dependency property to its ViewModel's property.
The custom control looks like:
public partial class MyCustomControl : Canvas
{
//Dependency Property
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyCustomControl));
private VisualCollection controls;
private TextBox textBox;
public string Text
{
get { return textBox.Text; }
set
{
SetValue(TextProperty, value);
textBox.Text = value;
}
}
//Constructor
public MyCustomControl ()
{
controls = new VisualCollection(this);
InitializeComponent();
textBox = new TextBox();
textBox.ToolTip = "Start typing a value.";
controls.Add(textBox);
//Bind the property
this.SetBinding(TextProperty, new Binding("Text") {Mode = BindingMode.TwoWay, Source = DataContext});
}
}
And the View Model looks like:
-------
public class MyCustomControlViewModel: ObservableObject
{
private string _text;
public string Text
{
get { return _text; }
set { _text = value; RaisePropertyChanged("Text");}
}
}
----------
This binding for "Text" Property is not working for some reason.
What I am trying to do is that in the actual implementation I want the text property of MyCustom Control to update when I update the Text property of my underlying ViewModel.
Any help regarding this is much appreciated.
After some research I finally figured out the problem with my code. I got this code working by creating a Static event handler that actually sets the new property value to the underlying public member of the dependency property. The Dependency property declaration is like :
//Dependency Property
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyCustomControl), new PropertyMetadata(null, OnTextChanged));
and then define the static method that sets the property is like :
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyCustomControl myCustomControl = (MyCustomControl)d;
myCustomControl.Text = (string) e.NewValue;
}
this is the only thing I was missing.
Cheers
Just bind to the dependency property
<MyCustomControl Text="{Binding Path=Text}" />
You should bind your member TextBox to your TextProperty instead. I am pretty sure that the binding in xaml on your Text property overrides the one you make in the constructor.

Categories

Resources