Invalid ContentPropertyAttribute on property 'Text' - c#

I am having trouble setting my ContentProperty to "Text". The error I am given is:
Invalid ContentPropertyAttribute on type 'MyType', property 'Text' not found.
The code behind looks like this:
[ContentProperty("Text")]
public partial class MyType: UserControl
{
public MyType()
{
InitializeComponent();
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text",
typeof (string),
typeof(MyType)));
public static string GetText(DependencyObject d)
{
return (string) d.GetValue(TextProperty);
}
public static void SetText(DependencyObject d, string value)
{
d.SetValue(TextProperty, value);
}
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
}
I have actually got it to work if I name the CLR property something other than the DependencyProperty - am I using DependencyProperties incorrectly?

I thought it would be because typeof(LinkText) should be typeof(MyType), but I was able to get my test project to compile. Could you post the XAML file which is causing the error?
EDIT: Followup
Your problem is the two static methods you have in your code sample. Try removing those, and it should compile and work. The static methods only work with Attached Properties, not Dependency Properties.

The error is coming from you're default value, set in:
... new PropertyMetadata(false) ...
Because the TextProperty is of type string, it expects a string for the default value. Try:
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof (string),
typeof(MyType),
new PropertyMetadata(String.Empty));

Related

Data-Binding with Custom Dependency-Property of UserControl is not working

I have a UserControl with 2 custom DependencyPropertys (ColumnsCount, RowsCount):
public partial class CabinetGrid : UserControl
{
public static readonly DependencyProperty ColumnsCountProperty =
DependencyProperty.Register("ColumnsCount", typeof (int), typeof (CabinetGrid));
public static readonly DependencyProperty RowsCountProperty =
DependencyProperty.Register("RowsCount", typeof (int), typeof (CabinetGrid));
public int ColumnsCount
{
get { return (int) GetValue(ColumnsCountProperty); }
set { SetValue(ColumnsCountProperty, value); }
}
public int RowsCount
{
get { return (int) GetValue(RowsCountProperty); }
set { SetValue(RowsCountProperty, value); }
}
}
And here's the DataBinding:
<view:CabinetGrid Grid.Column="1" Grid.Row="2" x:Name="GridRack" ColumnsCount="{Binding SelectedRoom.ColumnCount}" />
whereas the window's DataContext has a property SelectedRoom which invokes PropertyChanged-Event.
Thru debugging, I got to know that the DataContext of the UserControl is set properly.
However, when SelectedRoom has changed (=> I selected another item in a list), the DependencyProperty ColumnsCount of my UserControl is not updated.
I am very frustrated, as I already spent an entire day debugging through this unexpected shit, using tools like XAMLSpy and WpfSpoon.
Please, help.
EDIT:
Clemens already pointed out, that a breakpoint in the CLR-Property wrapping the DependencyProperty (ColumnsCount) is not fired. This is a major issue, since I have to call some methods on the change. I'm trying to use the PropertyChangedCallback, but am currently experiencing some errors.
In order to get notified about value changes of a dependency property, you should specify a PropertyChangedCallback in the PropertyMetadata when you register the property.
public static readonly DependencyProperty ColumnsCountProperty =
DependencyProperty.Register(
"ColumnsCount", typeof(int), typeof(CabinetGrid),
new PropertyMetadata(OnColumnsCountPropertyChanged));
private static void OnColumnsCountPropertyChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var cabinetGrid = (CabinetGrid)obj;
// do something with the CabinetGrid instance
}

WPF Binding on DependencyObject error

I want to pass an object as a parameter to a Converter. Since I can't do that using a ConverterParameter, I have used a DependencyProperty instead.
Here is the code -
public class FilteredColumnConverter : DependencyObject, IValueConverter
{
public DataGridFilter FilterObject
{
get { return (DataGridFilter) GetValue(FilterObjProperty); }
set { SetValue(FilterObjProperty, value); }
}
public static readonly DependencyProperty FilterObjProperty =
DependencyProperty.Register( "FilterObj",
typeof(DataGridFilter),
typeof(FilteredColumnConverter),
new PropertyMetadata(null));
// With implementations for Convert and ConvertBack
}
My XAML:
<UserControl.Resources>
<helpers:FilteredColumnConverter x:Key="filteredColumnConverter"
FilterObject="{Binding myFilterObj}"/>
</UserControl.Resources>
I'm getting the following error :
A Binding cannot be set on the FilterObject property of type FilteredColumnConverter. A Binding can only be set on a DependencyProperty of a DependencyObject.
What seems to be the problem? I have a FilterObject is a dependency property and I have followed the naming conventions as well.
try register DP with name FilterObject not FilterObj
DependencyProperty.Register("FilterObject", ...

Having trouble binding to a dependencyProperty

MyControl.xaml.cs
public string achName
{
get { return (string)this.GetValue(achNameProperty); }
set { this.SetValue(achNameProperty, value); }
}
public static readonly DependencyProperty achNameProperty = DependencyProperty.Register("achName", typeof(string), typeof(MyControl), new PropertyMetadata(null));
MainPage.xaml
<My:MyControl achName="{Binding Name}"/>
name has a value, but it doesn't seem to get send to the dependendcy (achName) property. How can I fix this?
ViewModel
public string Name { get { return "some random test value"; } }
other bindings to viewmodel do work, so the problem doesn't lie there.
The only reason i can see is that Binding to Name is failing. You can debug your bindings to see if its not failing. Refer to this - Debug Data Bindings

Can't bind an attached property to another dependency property

I' writing a control library. In this library there are some custom panels which are populated with user UIElements. Since every child element in my lib must have a "Title" property, I wrote the following:
// Attached properties common to every UIElement
public static class MyLibCommonProperties
{
public static readonly DependencyProperty TitleProperty =
DependencyProperty.RegisterAttached(
"Title",
typeof(String),
typeof(UIElement),
new FrameworkPropertyMetadata(
"NoTitle", new PropertyChangedCallback(OnTitleChanged))
);
public static string GetTitle( UIElement _target )
{
return (string)_target.GetValue( TitleProperty );
}
public static void SetTitle( UIElement _target, string _value )
{
_target.SetValue( TitleProperty, _value );
}
private static void OnTitleChanged( DependencyObject _d, DependencyPropertyChangedEventArgs _e )
{
...
}
}
Then, if I write this:
<dl:HorizontalShelf>
<Label dl:MyLibCommonProperties.Title="CustomTitle">1</Label>
<Label>1</Label>
<Label>2</Label>
<Label>3</Label>
</dl:HorizontalShelf>
everything works fine and the property gets the specified value, but if I try to bind that property to some other UIElement DependencyProperty like this:
<dl:HorizontalShelf>
<Label dl:MyLibCommonProperties.Title="{Binding ElementName=NamedLabel, Path=Name}">1</Label>
<Label>1</Label>
<Label>2</Label>
<Label Name="NamedLabel">3</Label>
</dl:HorizontalShelf>
an exception would be thrown: "A 'Binding' cannot be set on the 'SetTitle' property of type 'Label'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject."
What am I missing? Binding seems to work fine if instead of binding to "Name" I bind to some other attached property defined in MyLibCommonProperties.
Thanks in advance.
Replace the UIElement in your DependencyProperty definition to MyLibCommonProperties
public static readonly DependencyProperty TitleProperty =
DependencyProperty.RegisterAttached(
"Title",
typeof(String),
typeof(MyLibCommonProperties), // Change this line
new FrameworkPropertyMetadata(
"NoTitle", new PropertyChangedCallback(OnTitleChanged))
);
I think it might be because the binding implicitly uses the parent class specified to call SetTitle() so it is calling Label.SetTitle() instead of MyLibCommonProperties.SetTitle()
I had the same issue with some custom TextBox properties. If I used typeof(TextBox) then I couldn't bind to the value, but if I used typeof(TextBoxHelpers) then I could

WPF C# Recording Dependency object data modification

Am working with dependency objects here, not done much with them before but they look very useful.
Basically I've used these objects to be editable in a ListView. However, I then have to write these changes back to SQL. My question is, is there a way to record whether the data has been modified because I don't want to write back to SQL every time someone views the data. Currently I have this:
public class KPI : DependencyObject
{
public static readonly DependencyProperty DepartmentProperty = DependencyProperty.Register("Department", typeof(string), typeof(KPI), new UIPropertyMetadata(null));
public string Department
{
get { return (string)GetValue(DepartmentProperty); }
set { SetValue(DepartmentProperty, value); }
}
public static readonly DependencyProperty KPINumberProperty = DependencyProperty.Register("KPINumberProperty", typeof(int), typeof(KPI), new UIPropertyMetadata(null));
public int KPINumber
{
get { return (int)GetValue(KPINumberProperty); }
set { SetValue(KPINumberProperty, value); }
}
}
My idea was to have something like:
public static bool DataModified = false;
public static readonly DependencyProperty DepartmentProperty = DependencyProperty.Register("Department", typeof(string), typeof(KPI), new UIPropertyMetadata(null));
public string Department
{
get { return (string)GetValue(DepartmentProperty); }
set { SetValue(DepartmentProperty, value); DataModified = true; }
}
So every time something is edited the DataModified property will be set to TRUE, is this a good way of doing it? Or has somebody got a much better way of doing it?
Thanks in advance.
SumGuy.
This actually won't work if you're binding to the dependency property. The WPF binding engine does not actually use your CLR "Department" property, but rather uses "SetValue" on the dependency property directly. There is an easy solution to this though.
The UIPropertyMetadata has a field for a PropertyChangedCallback which will fire every time the value of the property is changed (either from a call to SetValue directly, or through the CLR property which is wrapping the SetValue call)
Here's an example:
public static readonly DependencyProperty DepartmentProperty =
DependencyProperty.Register("Department",
typeof(string),
typeof(KPI),
new UIPropertyMetadata(null, DepartmentPropertyChanged));
private static void DepartmentPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
KPI me = d as KPI;
if (me == null) return;
// Talk to your Business/Data layers here
}
public string Department
{
get { return (string)GetValue(DepartmentProperty); }
set { SetValue(DepartmentProperty, value); }
}
The DependencyObject (d) is the object who the property belongs to. In your case, this would be an instance of KPI.
For reference, here's a link to the UIPropertyMetadata MSDN documentation: http://msdn.microsoft.com/en-us/library/system.windows.uipropertymetadata.aspx
WPF binding system doesn't necessarily call the Department CLR property, instead it directly calls SetValue whenever it updates dependency property (in this case Department). That means, your CLR wrapper may not get called, which in turns means whatever code you've written in set block (of Department CLR property) would not be executed.
But don't worry, there is solution for it. While initializing DepartmentProperty you can pass a callback to UIPropertyMetadata which would be called everytime it updates the dependency property. All it means is that, you've to implement this:
public static readonly DependencyProperty DepartmentProperty = DependencyProperty.Register
(
"Department",
typeof(string),
typeof(KPI),
new UIPropertyMetadata(null, OnDepartmentChanged)
);
public string Department
{
get { return (string)GetValue(DepartmentProperty); }
set { SetValue(DepartmentProperty, value);}
}
static void OnDepartmentChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
(d as KPI).DataModified = true; //this is all you want!
}

Categories