WPF Dependency Property On Change Update Control - c#

I am currently trying to get a view to update when a dependency value changes.
I have copied the code from the view into it's parent and didn't use the dependency and it worked fine. I believe my issue is with how I am creating the DependencyProperty.
public partial class CULabelConfigControl : UserControl {
private CreditUnion CU { get; set; }
public static readonly DependencyProperty CUProperty = DependencyProperty.Register(
"CU",
typeof(CreditUnion),
typeof(CULabelConfigControl),
new FrameworkPropertyMetadata(null)
);
I currently receive an Error at run time:
"A 'Binding' cannot be set on the 'CU' property of type 'CULabelConfigControl'.
A 'Binding' can only be set on a DependencyProperty of a DependencyObject."
Any point in the right direction would be helpful. And let me know if I need to share any other details.

It should look like this:
public partial class CULabelConfigControl : UserControl
{
public static readonly DependencyProperty CUProperty =
DependencyProperty.Register(
nameof(CU),
typeof(CreditUnion),
typeof(CULabelConfigControl));
public CreditUnion CU
{
get { return (CreditUnion)GetValue(CUProperty); }
set { SetValue(CUProperty, value); }
}
}
In the XAML of your UserControl, you would bind to this property by specifying the UserControl as RelativeSource, e.g.
<Label Content="{Binding CU, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
If you need to get notified in the UserControl class whenever the property value changes, you should register a PropertyChangedCallback:
public static readonly DependencyProperty CUProperty =
DependencyProperty.Register(
nameof(CU),
typeof(CreditUnion),
typeof(CULabelConfigControl),
new PropertyMetadata(CUPropertyChanged));
private static void CUPropertyChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var control = (CULabelConfigControl)obj;
// react on value change here
}

Related

WPF : How to access observablecollection in a nested usercontrol?

in my application I'm using two usercontrol : UserControl1 is the main one, inside it, I have UserControl2 used six times.
UserControl2 has several combobox, and I would like to fill them dynamically from the final application. As a start I'm trying to bind data to one of them.
The combobox in UserControl2 look like this :
<ComboBox x:Name="VidTransform" Template="{DynamicResource BaseComboBoxStyle}" ItemContainerStyle="{DynamicResource BaseComboBoxItemStyle}" Grid.Row="1" ItemsSource="{Binding Path=DataContext.VidTransformsNames,ElementName=Ch_Parameters, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedValue="{Binding Path=SelectedTransform,ElementName=Ch_Parameters, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
At the moment I'm only able to fill it manually, using this ObservableCollection (all strings shows up correctly) :
private ObservableCollection<string> _VidTransformsNames = new ObservableCollection<string>(new[] { "test0", "test1", "test2", "test3", "test4", "test5" });
public ObservableCollection<string> VidTransformsNames
{
get { return _VidTransformsNames; }
set { _VidTransformsNames = value; }
}
In UserControl1 (which contains UserControl2), I tried to create an other ObservableCollection and fill it dynamically at runtime in my final application.
Here it is :
private ObservableCollection<string> _VideoTransformsNames = new ObservableCollection<string>(new[] { "Test0", "Test1", "Test2", "Test3", "Test4", "Test5" });
public ObservableCollection<string> VideoTransformsNames
{
get { return _VideoTransformsNames; }
set { _VideoTransformsNames = value; }
}
And then binding :
<local:UserControl1 VidTransformsNames="{Binding Path=VideoTransformsNames, ElementName=cmix, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
I'm beginner, but here I'm wrong for sure, as I get this error :
A 'Binding' cannot be set on the 'VidTransformsNames' property of type 'UserControl1'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
How can I access and fill up at runtime the observablecollection of UserControl2 if it is nested in UserControl1 ?
This is because your property needs to be declared properly as DependencyProperty
Dependency properties and the WPF property system extend property
functionality by providing a type that backs a property, as an
alternative implementation to the standard pattern of backing the
property with a private field. The name of this type is
DependencyProperty. The other important type that defines the WPF
property system is DependencyObject. DependencyObject defines the base
class that can register and own a dependency property.
Please follow this https://msdn.microsoft.com/library/ms753358(v=vs.100).aspx, or Dependency Property Overview https://msdn.microsoft.com/pl-pl/library/ms752914(v=vs.100).aspx
Example taken from above articles:
public static readonly DependencyProperty IsSpinningProperty =
DependencyProperty.Register(
"IsSpinning", typeof(Boolean),
...
);
public bool IsSpinning
{
get { return (bool)GetValue(IsSpinningProperty); }
set { SetValue(IsSpinningProperty, value); }
}
Let's try to set it to your code:
public static readonly DependencyProperty VideoTransformsNamesProperty =
DependencyProperty.Register("VideoTransformsNames", typeof(ObservableCollection<string>), typeof(UserControl1));
public string VideoTransformsNames
{
get
{
return this.GetValue(VideoTransformsNamesProperty) as ObservableCollection<string>;
}
set
{
this.SetValue(VideoTransformsNamesProperty, value);
}
}

Binding to a property doesn't work

this is the Code behind of user control
public delegate void YardSelectionChangedDelegate();
public event YardSelectionChangedDelegate YardSelectionChanged;
public static readonly DependencyProperty SelectedYardIdProperty =
DependencyProperty.Register(
"SelectedYardId",
typeof(long),
typeof(YardSelectorUserControl),
new UIPropertyMetadata(null));
And this is the Property:
public long SelectedYardId
{
get { return (long)GetValue(SelectedYardIdProperty); }
set { SetValue(SelectedYardIdProperty, value); }
}
And this is the Binding in the parent window:
SelectedYardId="{Binding Path=YardId,UpdateSourceTrigger=PropertyChanged}"
The problem is that the Set of the property never work and cursor never reach the Set body.
thanks indeed.
That is because binding engine doesn't use your set or get accessors for setting or getting a property. It uses SetValue and GetValue of the DependencyObject directly. In order to trigger an event while changing a dependency property you need to define a callback delegate while registering your dependency property like this:
public static readonly DependencyProperty SelectedYardIdProperty =
DependencyProperty.Register(
"SelectedYardId",
typeof(long),
typeof(YardSelectorUserControl),
new UIPropertyMetadata(OnSelectedYardIdChanged));
public static void OnSelectedYardIdChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// Action
}
Maybe you should Implement INotifyPropertyChanged in your model, and change "YardId" property to raise PropertyChanged event in the "Set" body.

Binding to dependencyproperty on a per object basis

I have the following class schema
public Class Test : DependencyObject
{
private DependencyProperty _thickness = DependencyProperty.Register("Thickness", typeof(double), typeof(CounterDataStreamWrapper));
public double Thickness
{
get
{
return (double)GetValue(this._thickness);
}
set
{
SetValue(this._thickness, value);
}
}
... Rest of the code
}
Essentially I have a collection of Test objects, and I want to bind the Thickness value for each one to its corresponding UI element. I am not too familiar with C# binding. When I try to create multiple objects, I am running into "DependencyProperty is already registered" issue. I am sure that I am just missing some key concept for binding to DependencyProperty.
Any help is appreciated!
You are registering the Thickness DependencyProperty on the CounterDataStreamWrapper type and private per instance.
Make the DependencyProperty public static and register it for the class Test.
public static DependencyProperty Thickness =
DependencyProperty.Register("Thickness", typeof(double), typeof(Test));
It's supposed to be static. Like this:
private static DependencyProperty _thickness ...

How to create your own properties for element in SilverLight

Can someone help me with this question?) In My XAML I have Listbox element. I want to add my user property into it(in my case - ConnectorStyle)
My XAML code:
<ListBox ItemsSource="{Binding Nodes}" ItemsPanel="{StaticResource CanvasItemsPanelTemplate}"
ItemTemplate="{StaticResource NodePictureTemplate}"
ItemContainerStyle="{StaticResource CanvasItemStyle}"
ConnectorStyle="{StaticResource ConnectorLineStyle}"/>
In my Model I have prepared this property:
public partial class MainPage : UserControl
{
public static readonly DependencyProperty ConnectorStyleProperty = DependencyProperty.Register(
"ConnectorStyle", typeof(Style), typeof(NodePicture), null);
public MainPage()
{
InitializeComponent();
}
public Style ConnectorStyle
{
get { return (Style)GetValue(ConnectorStyleProperty); }
set { SetValue(ConnectorStyleProperty, value); }
}
}
But I is a mistake - Cannot resolve ConnectorStyle.
Is there a simple (or a right way ) way of doing this?
There are two ways to do this: Either you can write a subclass for the ListBox that adds the DependencyProperty or you can write an attached property.
In your case you probably want to write a subclass that adds the property. Try something like this:
public class MyListBox : ListBox
{
public static readonly DependencyProperty ConnectorStyleProperty = DependencyProperty.Register(
"ConnectorStyle", typeof(Style), typeof(MyListBox), null);
public Style ConnectorStyle
{
get { return (Style)GetValue(ConnectorStyleProperty); }
set { SetValue(ConnectorStyleProperty, value); }
}
}
This will add a new type of ListBox that you can add in your xaml code. It will have all the same properties as a regular ListBox, but it will also have the ConnectorStyle property.
If you need to respond to changes to the ConnectorStyle property in your listbox then you should change the code for the Dependency Property, but that is outside the scope of this question.
And in XAML it shoul be :
<local:ListBoxEx
ConnectorStyle="{StaticResource ConnectorLineStyle}"/>

Variable Bindings in WPF

I’m creating a UserControl for a rich TreeView (one that has context menus for renaming nodes, adding child nodes, etc.). I want to be able to use this control to manage or navigate any hierarchical data structures I will create. I currently have it working for any data structure that implements the following interface (the interface need not actually be implemented, however, only the presence of these members is required):
interface ITreeItem
{
string Header { get; set; }
IEnumerable Children { get; }
}
Then in my UserControl, I use templates to bind my tree to the data structure, like so:
<TextBlock x:Name="HeaderTextBlock" Text="{Binding Path=Header}" />
What I would like to do is define the name of each of these members in my RichTreeView, allowing it to adapt to a range of different data structures, like so:
class MyItem
{
string Name { get; set; }
ObservableCollection<MyItem> Items;
}
<uc:RichTreeView ItemSource={Binding Source={StaticResource MyItemsProvider}}
HeaderProperty="Name" ChildrenProperty="Items" />
Is there any way to expose the Path of a binding inside a UserControl as a public property of that UserControl? Is there some other way to go about solving this problem?
Perhaps this might help:
Create a new Binding when you set the HeaderProperty property on the Header dependency property:
Header property is your normal everyday DependencyProperty:
public string Header
{
get { return (string)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(ownerclass));
and the property of your HeaderProperty works as follows:
public static readonly DependencyProperty HeaderPropertyProperty =
DependencyProperty.Register("HeaderProperty", typeof(string), typeof(ownerclass), new PropertyMetadata(OnHeaderPropertyChanged));
public string HeaderProperty
{
get { return (string)GetValue(HeaderPropertyProperty); }
set { SetValue(HeaderPropertyProperty, value); }
}
public static void OnHeaderPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
if (args.NewValue != null)
{
ownerclass c = (ownerclass) obj;
Binding b = new Binding();
b.Path = new PropertyPath(args.NewValue.ToString());
c.SetBinding(ownerclass.HeaderProperty, b);
}
}
HeaderProperty is your normal everyday DependencyProperty, with a method that is invoked as soon as the HeaderProperty changes. So when it changes , it creates a binding on the Header which will bind to the path you set in the HeaderProperty. :)

Categories

Resources