Two-Way Dependency Property Binding with User Control - wpf

I have a simple User Control:
public partial class FreqSpreadUC : UserControl
{
public FreqSpreadUC()
{
InitializeComponent();
FreqOne = "trying to pass this on to the parent";
}
public String FreqOne
{
get { return (String)GetValue(FreqOneProperty); }
set { SetValue(FreqOneProperty, value); }
}
// Using a DependencyProperty as the backing store for FreqOne. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FreqOneProperty =
DependencyProperty.Register("FreqOne", typeof(String), typeof(FreqSpreadUC));
}
Then I am consuming it as follows:
<spread:FreqSpreadUC FreqOne="{Binding TestFreqOne}" />
When the underlying user control changes its FreqOne dependency property, I want TestFreqOne to change as well. I am trying to create a user control that will "output" a result to the parent control. How would I go about doing this? Thank you.

Your question title already suggests it. You need a two-way binding:
<spread:FreqSpreadUC FreqOne="{Binding TestFreqOne, Mode=TwoWay}" />
Alternatively you might register property metadata with your dependency property that makes it bind two-way by default:
public static readonly DependencyProperty FreqOneProperty =
DependencyProperty.Register(
"FreqOne", typeof(String), typeof(FreqSpreadUC)
new FrameworkPropertyMetadata(
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

Related

How to add a binding to a xaml binding within a behavior?

I have a behavior with a xaml interface of:
<i:Interaction.Behaviors>
<b:ChartCanvasItemBehavior
Source="{Binding MovieUri}"
Timeline="{Binding Path=Timeline, ElementName=ChartCanvasRightPanel, Mode=OneWayToSource}"
/>
</i:Interaction.Behaviors>
The behavior creates an adorner that does:
public double Timeline
{
get { return (double)GetValue(TimelineProperty); }
set { SetValue(TimelineProperty, value); }
}
// Using a DependencyProperty as the backing store for Timeline. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TimelineProperty =
DependencyProperty.Register("Timeline", typeof(double), typeof(MovieControlForChartCanvas), new UIPropertyMetadata(0.0));
To link the two in the behavior, I have:
var bindingMovieTime = new Binding
{
Source = mc,
Path = new PropertyPath(MovieControlForChartCanvas.TimelineProperty)
};
BindingOperations.SetBinding(this, iTimelineProperty, bindingMovieTime);
#region [Dependency Properties used to bind to the MovieControlForChartCanvas]
// These dependecy properties have to be DIFFERENT then the dependency properties used for the ChartCanvasItemBehavior xaml interface.
// Using the same dependecy property for both bindings to the MovieControl and the Xaml interface results in losing one of the first bindings (i.e., the xaml binding).
public double iTimeline
{
get { return (double)GetValue(iTimelineProperty); }
set { SetValue(iTimelineProperty, value); }
}
// Using a DependencyProperty as the backing store for iTimeline. This enables animation, styling, binding, etc...
public static readonly DependencyProperty iTimelineProperty =
DependencyProperty.Register("iTimeline", typeof(double), typeof(ChartCanvasItemBehavior), new PropertyMetadata(0.0,
(s, e) =>
{
ChartCanvasItemBehavior d = s as ChartCanvasItemBehavior;
d.Timeline = (double)e.NewValue;
}
));
#endregion
public double Timeline
{
get { return (double)GetValue(TimelineProperty); }
set { SetValue(TimelineProperty, value); }
}
// Using a DependencyProperty as the backing store for Timeline. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TimelineProperty =
DependencyProperty.Register("Timeline", typeof(double), typeof(ChartCanvasItemBehavior ), new PropertyMetadata(0.0));
This seems to require a second property between the behavior and the adorner. If I use one property for both the behavior interface and the behavior-to-adorner interface, the first assignment to that behavior, i.e, from the xaml, gets overwritten by the binding to the adorner.
Can this be done using only one dependency property in the behavior with multibinding?
If so, how?
To rephrase, is it possible to use one dependency property in the behavior to serve as an interface in both the xaml and to the adorner? (multibinding?)
Thanks for any suggestions.

Why throw the error of "Cannot add content to an object of type" by customcontrol?

I wrote a customcontrol inhert Control and add a DependencyProperty content which I want it to be the same as the content of the button control.
Here is the code:
[System.ComponentModel.Bindable(true)]
public object Content
{
get { return (object)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
// Using a DependencyProperty as the backing store for Content. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ContentProperty =
DependencyProperty.Register("Content", typeof(object), typeof(SContent), null);
But after I reference the dll and run the program, WPF threw this error:
What's wrong with this? Would you please help me? Thank you.
If you want your custom control to support direct content in XAML, you should decorate it with the ContentPropertyAttribute :
[ContentProperty("Content")]
public class SContent : Control
{
[System.ComponentModel.Bindable(true)]
public object Content
{
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public static readonly DependencyProperty ContentProperty =
DependencyProperty.Register(nameof(Content), typeof(object), typeof(SContent), null);
}
But if you just want a Content property you might as well inherit from ContentControl instead of Control. Then you also get a ContentTemplate property and some other stuff "for free".

WPF Binding to a property of a custom control

I've created a custom control, means a class deriving from control associating a default lookless theme defined via Themes/Generic.xaml. So far so good.
Now, I want to use the control like any other of the main WPF-controls (textbox, listbox, label, textblock, ...) and bind to the defined properties.
The custom control defines a property called Value, that I like to set a Binding to. But nothing ever is written to the bound property in the DataContext.
Well, here's what I've got so far:
In Custom Control class, there is as follows:
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(string), typeof(MyClass),
new FrameworkPropertyMetadata("", new PropertyChangedCallback(onValuePropertyChangedCallback)));
private static void onValuePropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
MyClass myClass = (MyClass)sender;
myClass.Value = (string)args.NewValue;
}
public string Value
{
get { return (string) GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
When I use the control, it's like that
<local:MyClass MyValue="{Binding CurrentValue}" ... />
The CurrentValue-property of the DataContext is never affected, never changes it's value.
What am I doing wrong?
The Binding to should be two-way in order to update the source property:
<local:MyClass Value="{Binding CurrentValue, Mode=TwoWay}" ... />
If you want this to be the default binding mode, you could set an appropriate flag when you register your property:
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
nameof(Value), typeof(string), typeof(MyClass),
new FrameworkPropertyMetadata(
"", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
Note that your onValuePropertyChangedCallback was entirely redundant. You don't need to set the property again, when its value has just changed.

Why a Custom Dependency Property is not Showing in User Control's intellisense?

I created a User Control and in code behind, I added the following DP. When I switch to XAML and try to type the name of the property next to the UserControl tag, for example "Test", it doesn't show up. I wonder what could be missing here.
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test", typeof(String), typeof(UserControl1));
You also need to implement the CLR Wrapper for that property:
public string Test
{
get { return (string)GetValue(TestProperty); }
set { SetValue(TestProperty, value); }
}

WPF Binding to a custom property in a custom control

I have a custom text box defined as follows:
public class CustomTextBox : TextBox
{
public static DependencyProperty CustomTextProperty =
DependencyProperty.Register("CustomText", typeof(string),
typeof(CustomTextBox));
static CustomTextBox()
{
TextProperty.OverrideMetadata(typeof(SMSTextBox),
new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.Journal |
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(CustomTextBox_OnTextPropertyChanged));
}
public string CustomText
{
get { return (string)GetValue(CustomTextProperty); }
set { SetValue(CustomTextProperty, value); }
}
private static void CustomTextBox_OnTextPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
CustomTextBox customTextBox = d as CustomTextBox;
customTextBox.SetValue(CustomTextProperty, e.NewValue);
}
}
I'm binding the Custom Text property in the XAML -
<local:CustomTextBox CustomText="{Binding ViewModelProperty}" />
The problem I'm facing is that when I enter anything in the CustomTextBox, the changes are not reflected in the ViewModelProperty i.e. the ViewModelProperty is not getting updated. The CustomTextProperty is getting updated but I suppose I need to do something extra to make the binding work as well.
What am I not doing? I would appreciate any help regarding this.
Thank you
I guess the binding needs to be two-way.
<local:CustomTextBox
CustomText="{Binding ViewModelProperty, Mode=TwoWay}" />
You wouldn't need to specify the Mode if you made the CustomText property bind two-way by default:
public static readonly DependencyProperty CustomTextProperty =
DependencyProperty.Register(
"CustomText", typeof(string), typeof(CustomTextBox),
new FrameworkPropertyMetadata(
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
You may also have to define a PropertyChangedCallback for the CustomText property that updates the Text property (i.e. the other direction of what you have implemented now). Otherwise the TextBox won't display anything that is initially contained in the ViewModel property and of course woudln't be updated when the ViewModel property changes.

Resources