I am writing two dependency properties and I keep getting the "[Property] was already registered by 'FrameworkElement'" error in the design window of VS11. Here is a snippet of my code
public static readonly DependencyProperty IsEditingNumberProperty =
DependencyProperty.Register("IsEditingNumbers", typeof(bool), typeof(FrameworkElement),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));
the problem seems to be the 3rd parameter (owner parameter typeof(FrameworkElement)). If I set the 3rd parameter to the class the contains two dependency properties, the error goes away, but I cannot use the properties directly from xaml. I would have to add ownership for each dependency property before I use it.
Actually, It does render correctly, but only when I first open it. Immediately after the first render it will give me an exception. At runtime, it seems to work perfectly.
Am I doing something wrong and is there a way to get rid of this annoying error?
---- Edit -----
Here is my custom class (includes 2 of the Dependency Properties):
public partial class EditableTextBox : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty IsEditingNumberProperty =
DependencyProperty.Register("IsEditingNumber", typeof(bool), typeof(FrameworkElement),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(FrameworkElement),
new FrameworkPropertyMetadata("0", FrameworkPropertyMetadataOptions.AffectsRender)
{
CoerceValueCallback = new CoerceValueCallback((sender,value) =>
{
return expressionRestaraint.Match((string)value).Value;
})
});
#endregion
public static Regex expressionRestaraint = new Regex("[-a-zA-z0-9+*.\\(\\)\\[\\]\\{\\}]*");
public string Text
{
get { (string)GetValue(TextProperty); }
set
{
SetValue(TextProperty, value);
tbxValue.Text = (string)GetValue(TextProperty);
}
}
public bool IsEditingNumber
{
get
{
return (bool)GetValue(IsEditingNumberProperty);
}
set
{
bool old = (bool)GetValue(IsEditingNumberProperty);
if (old != value)
{
if (!value)
stopEditing();
else
startEditing();
SetValue(IsEditingNumberProperty, value);
}
}
} . . .
Use in Main Class:
<Window x:Class="VisualMathExpression.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:edit="clr-namespace:VisualMathExpression.EditableTextBox"
xmlns:all="clr-namespace:VisualMathExpression"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<edit:EditableTextBox HorizontalAlignment="Center" VerticalAlignment="Center"
Text="af" IsEditingNumber="True" /> . . .
--- Edit ---
Wrapper fixed (problem that cause xaml property not to change when ownership belonged to the declared class)
public partial class EditableTextBox : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty IsEditingNumberProperty =
DependencyProperty.Register("IsEditingNumber", typeof(bool), typeof(EditableTextBox),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender)
{
PropertyChangedCallback = new PropertyChangedCallback((sender, arg) =>
{
EditableTextBox ed = sender as EditableTextBox;
if (!(bool)arg.NewValue)
ed.stopEditing();
else
ed.startEditing();
}),
});
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(EditableTextBox),
new FrameworkPropertyMetadata("0", FrameworkPropertyMetadataOptions.AffectsRender)
{
PropertyChangedCallback = new PropertyChangedCallback((sender,arg) =>
{
EditableTextBox ed = sender as EditableTextBox;
ed.tbxValue.Text = arg.NewValue as string;
}),
CoerceValueCallback = new CoerceValueCallback((sender,value) =>
{
return expressionRestaraint.Match((string)value).Value;
})
});
#endregion
public static Regex expressionRestaraint = new Regex("[-a-zA-z0-9+*.\\(\\)\\[\\]\\{\\}]*");
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public bool IsEditingNumber
{
get { return (bool)GetValue(IsEditingNumberProperty); }
set { SetValue(IsEditingNumberProperty, value); }
}
The third parameter ownerType of the DependencyProperty.Register method must be the class that declares the property.
If your class is MyClass the declaration would have to look like this:
public class MyClass : DependencyObject
{
public static readonly DependencyProperty IsEditingNumberProperty =
DependencyProperty.Register(
"IsEditingNumber", typeof(bool), typeof(MyClass), ...);
// CLR wrapper
public bool IsEditingNumber
{
get { return (bool)GetValue(IsEditingNumberProperty); }
set { SetValue(IsEditingNumberProperty, value); }
}
}
Related
I have a user control in WPF which I want to pass a list of items to when I use the user control in another window (the user control contains a ComboBox and label and has some important functionality). This works fine if I have a single control on my page, but if I have two I get the values listed from both my user controls, presumably because the DependencyProperty is static. I can't remove the static as it throws an error when registering the dependency property.
public static readonly DependencyProperty ComboBoxValuesProperty =
DependencyProperty.Register("ComboBoxValues", typeof(ObservableCollection<ComboBoxValue>), typeof(SystemConfigComboBox),
new PropertyMetadata(new ObservableCollection<ComboBoxValue>()));
public ObservableCollection<ComboBoxValue> ComboBoxValues
{
get { return GetValue(ComboBoxValuesProperty) as ObservableCollection<ComboBoxValue>; }
set { SetValue(ComboBoxValuesProperty, value); }
}
Below shows both user controls ComboBoxes containing Value1 and Value2
<customEditors:SystemConfigComboBox SystemConfigEntry="Entry1" ComboBoxLabel="Combo 1" ComboBoxWidth="300">
<customEditors:SystemConfigComboBox.ComboBoxValues>
<customEditors:ComboBoxValue DisplayValue="Value1" ActualValue="VALUE1" />
</customEditors:SystemConfigComboBox.ComboBoxValues>
</customEditors:SystemConfigComboBox>
<customEditors:SystemConfigComboBox SystemConfigEntry="Entry2" ComboBoxLabel="Combo 2" ComboBoxWidth="300">
<customEditors:SystemConfigComboBox.ComboBoxValues>
<customEditors:ComboBoxValue DisplayValue="Value2" ActualValue="VALUE2" />
</customEditors:SystemConfigComboBox.ComboBoxValues>
</customEditors:SystemConfigComboBox>
and just for information the ComboBoxValue class:-
public class ComboBoxValue : FrameworkElement
{
public static readonly DependencyProperty DisplayValueProperty =
DependencyProperty.Register("DisplayValue", typeof(string), typeof(ComboBoxValue));
public static readonly DependencyProperty ActualValueProperty =
DependencyProperty.Register("ActualValue", typeof(string), typeof(ComboBoxValue));
public string DisplayValue
{
get { return (string)GetValue(DisplayValueProperty); }
set { SetValue(NameProperty, value); }
}
public string ActualValue
{
get { return (string)GetValue(ActualValueProperty); }
set { SetValue(ActualValueProperty, value); }
}
}
You should initialize the ObservableCollection in the constructor of the control class and not in the DependencyProperty.Register method:
public class SystemConfigComboBox
{
public SystemConfigComboBox()
{
ComboBoxValues = new ObservableCollection<ComboBoxValue>();
}
public static readonly DependencyProperty ComboBoxValuesProperty =
DependencyProperty.Register("ComboBoxValues", typeof(ObservableCollection<ComboBoxValue>), typeof(SystemConfigComboBox)));
...
}
Please refer to MSDN for more information about this: https://msdn.microsoft.com/en-us/library/aa970563(v=vs.110).aspx
I'm currently working on a user control and stuck with the custom properties of the dependency object class
IsEnabled gets recognized but not FooText
XAML:
<ScrollViewer VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden"
sc:TouchScrolling.IsEnabled = "true"
Grid.Row="0" Grid.Column="1">
I need to set more properties on the sc:TouchScrolling element, but VS keeps complaining that it can't find the property.
TouchScrolling element inherits from Dependency Object
public class TouchScrolling : DependencyObject
{
public bool IsEnabled
{
get { return (bool)GetValue(IsEnabledProperty); }
set { SetValue(IsEnabledProperty, value); }
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(TouchScrolling), new UIPropertyMetadata(false, IsEnabledChanged));
//FooText is not recognized
public string FooText
{
get { return (string)GetValue(FooTextProperty); }
set { SetValue(FooTextProperty, value); }
}
You seem to be missing the FooText DependencyProperty...
public static readonly DependencyProperty FooTextProperty =
DependencyProperty.RegisterAttached("FooText", typeof(string), typeof(TouchScrolling), null);
I want to add custom attributes to my user control such that the UserControl will then use that attribute when displaying (or turning on / off) various options
i.e.
<toolkit:UC_TitleBar title="My Application Title" showCloseButton="false" />
How do I do this?
What you need are dependency properties
public class UC_TitleBar : UserControl
{
public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register("ShowCloseButton",
typeof(Boolean), typeof(UC_TitleBar), new FrameworkPropertyMetadata(false));
public bool ShowCloseButton
{
get { return (bool)GetValue(ShowCloseButtonProperty); }
set { SetValue(ShowCloseButtonProperty, value); }
}
}
//add dependency property
public static DependencyProperty MyTestProperty;
//init dependency property in static control constructor
static MyControl()
{
var myTestPropertyMetadata = new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender, MyTestPropertyChanged);
MyTestProperty= DependencyProperty.Register("MyTest",
typeof(string),
typeof(MyControl),
myTestPropertyMetadata );
}
//implement property
public String MyTest
{
get { return (String)GetValue(MyTestProperty); }
set
{
SetValue(MyTestProperty, value);
}
}
//using in xaml
<MyControls:MyControl MyTest="dfdsf" />
read more about dependency properties in MSDN
I am writing two dependency properties and I keep getting the "[Property] was already registered by 'FrameworkElement'" error in the design window of VS11. Here is a snippet of my code
public static readonly DependencyProperty IsEditingNumberProperty =
DependencyProperty.Register("IsEditingNumbers", typeof(bool), typeof(FrameworkElement),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));
the problem seems to be the 3rd parameter (owner parameter typeof(FrameworkElement)). If I set the 3rd parameter to the class the contains two dependency properties, the error goes away, but I cannot use the properties directly from xaml. I would have to add ownership for each dependency property before I use it.
Actually, It does render correctly, but only when I first open it. Immediately after the first render it will give me an exception. At runtime, it seems to work perfectly.
Am I doing something wrong and is there a way to get rid of this annoying error?
---- Edit -----
Here is my custom class (includes 2 of the Dependency Properties):
public partial class EditableTextBox : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty IsEditingNumberProperty =
DependencyProperty.Register("IsEditingNumber", typeof(bool), typeof(FrameworkElement),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(FrameworkElement),
new FrameworkPropertyMetadata("0", FrameworkPropertyMetadataOptions.AffectsRender)
{
CoerceValueCallback = new CoerceValueCallback((sender,value) =>
{
return expressionRestaraint.Match((string)value).Value;
})
});
#endregion
public static Regex expressionRestaraint = new Regex("[-a-zA-z0-9+*.\\(\\)\\[\\]\\{\\}]*");
public string Text
{
get { (string)GetValue(TextProperty); }
set
{
SetValue(TextProperty, value);
tbxValue.Text = (string)GetValue(TextProperty);
}
}
public bool IsEditingNumber
{
get
{
return (bool)GetValue(IsEditingNumberProperty);
}
set
{
bool old = (bool)GetValue(IsEditingNumberProperty);
if (old != value)
{
if (!value)
stopEditing();
else
startEditing();
SetValue(IsEditingNumberProperty, value);
}
}
} . . .
Use in Main Class:
<Window x:Class="VisualMathExpression.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:edit="clr-namespace:VisualMathExpression.EditableTextBox"
xmlns:all="clr-namespace:VisualMathExpression"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<edit:EditableTextBox HorizontalAlignment="Center" VerticalAlignment="Center"
Text="af" IsEditingNumber="True" /> . . .
--- Edit ---
Wrapper fixed (problem that cause xaml property not to change when ownership belonged to the declared class)
public partial class EditableTextBox : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty IsEditingNumberProperty =
DependencyProperty.Register("IsEditingNumber", typeof(bool), typeof(EditableTextBox),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender)
{
PropertyChangedCallback = new PropertyChangedCallback((sender, arg) =>
{
EditableTextBox ed = sender as EditableTextBox;
if (!(bool)arg.NewValue)
ed.stopEditing();
else
ed.startEditing();
}),
});
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(EditableTextBox),
new FrameworkPropertyMetadata("0", FrameworkPropertyMetadataOptions.AffectsRender)
{
PropertyChangedCallback = new PropertyChangedCallback((sender,arg) =>
{
EditableTextBox ed = sender as EditableTextBox;
ed.tbxValue.Text = arg.NewValue as string;
}),
CoerceValueCallback = new CoerceValueCallback((sender,value) =>
{
return expressionRestaraint.Match((string)value).Value;
})
});
#endregion
public static Regex expressionRestaraint = new Regex("[-a-zA-z0-9+*.\\(\\)\\[\\]\\{\\}]*");
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public bool IsEditingNumber
{
get { return (bool)GetValue(IsEditingNumberProperty); }
set { SetValue(IsEditingNumberProperty, value); }
}
The third parameter ownerType of the DependencyProperty.Register method must be the class that declares the property.
If your class is MyClass the declaration would have to look like this:
public class MyClass : DependencyObject
{
public static readonly DependencyProperty IsEditingNumberProperty =
DependencyProperty.Register(
"IsEditingNumber", typeof(bool), typeof(MyClass), ...);
// CLR wrapper
public bool IsEditingNumber
{
get { return (bool)GetValue(IsEditingNumberProperty); }
set { SetValue(IsEditingNumberProperty, value); }
}
}
I have a string dependency property (SearchText), when updated, needs to update a collection dependency property (Results).
My collection dp:
public IEnumerable<string> Results{
get { return (IEnumerable<string>) GetValue(ResultsProperty); }
set { SetValue(ResultsProperty, value); }
}
public static readonly DependencyProperty ResultsProperty=
DependencyProperty.Register("Results", typeof(IEnumerable<string>), typeof(MainWindowVM), new UIPropertyMetadata(new List<string>()));
I tried this with no luck. i put a breakpoint at the Results = .... line and it never got hit.
public string SearchText{
get { return (string) GetValue(SearchTextProperty); }
set {
Results =
from T in Tree.GetPeople(value)
select T.FullName;
SetValue(SearchTextProperty, value);
}
}
public static readonly DependencyProperty SearchTextProperty=
DependencyProperty.Register("SearchText", typeof(string), typeof(MainWindowVM), new UIPropertyMetadata(""));
XAML:
<TextBox DockPanel.Dock="Top" Text="{Binding SearchValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<ListBox DockPanel.Dock="Top" ItemsSource="{Binding NameResults}" SelectedItem="{Binding Search}" />
When setting a dependency property in XAML or through a binding, the runtime will always bypass the instance property alias and directly call GetValue and SetValue. It is because of this that your instance setter isn't being invoked.
What you may wish to consider doing is registering a method with the dependency property which will be invoked when the property changes. This is most easily done when creating the PropertyMetadata for the dependency property.
I believe the following example does what you're looking to do. In the example, my class has two depencency properties aliased as First and Second. When I set the value for First, my change handler is invoked and I set the value of Second.
public class DependencyPropertyTest : DependencyObject
{
public static readonly DependencyProperty FirstProperty;
public static readonly DependencyProperty SecondProperty;
static DependencyPropertyTest()
{
FirstProperty = DependencyProperty.Register("FirstProperty",
typeof(bool),
typeof(DependencyPropertyTest),
new PropertyMetadata(false, FirstPropertyChanged));
SecondProperty = DependencyProperty.Register("SecondProperty",
typeof(string),
typeof(DependencyPropertyTest),
new PropertyMetadata(null));
} // End constructor
private bool First
{
get { return (bool)this.GetValue(FirstProperty); }
set { this.SetValue(FirstProperty, value); }
} // End property First
private string Second
{
get { return (string)this.GetValue(SecondProperty); }
set { this.SetValue(SecondProperty, value); }
} // End property Second
private static void FirstPropertyChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs ea)
{
DependencyPropertyTest instance = dependencyObject as DependencyPropertyTest;
if (instance == null)
{
return;
}
instance.Second = String.Format("First is {0}.", ((bool)ea.NewValue).ToString());
} // End method FirstPropertyChanged
} // End class DependencyPropertyTest
I hope that helps.
As I commented, the currently accepted answer is correct in the principle, except that it MUST use the SetCurrentValue method instead of doing a simple assignment. See this answer for more explanation about it.
Here is the same code with this fix:
public class DependencyPropertyTest : DependencyObject
{
public static readonly DependencyProperty FirstProperty;
public static readonly DependencyProperty SecondProperty;
static DependencyPropertyTest()
{
FirstProperty = DependencyProperty.Register("FirstProperty",
typeof(bool),
typeof(DependencyPropertyTest),
new PropertyMetadata(false, FirstPropertyChanged));
SecondProperty = DependencyProperty.Register("SecondProperty",
typeof(string),
typeof(DependencyPropertyTest),
new PropertyMetadata(null));
} // End constructor
private bool First
{
get { return (bool)this.GetValue(FirstProperty); }
set { this.SetValue(FirstProperty, value); }
} // End property First
private string Second
{
get { return (string)this.GetValue(SecondProperty); }
set { this.SetValue(SecondProperty, value); }
} // End property Second
private static void FirstPropertyChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs ea)
{
DependencyPropertyTest instance = dependencyObject as DependencyPropertyTest;
if (instance == null)
{
return;
}
// SetCurrentValue should be used here!
instance.SetCurrentValue(SecondProperty,
String.Format("First is {0}.", ((bool)ea.NewValue).ToString());
} // End method FirstPropertyChanged
} // End class DependencyPropertyTest
The Order that you put on it your dependency property is very important
the fist one put in the class file, will be executed fist then the one down to it
class A {
dependecy 1
dependecy 2
dependecy 3
}
it will be called in the order set on the class, so just order your dependency on the order you want
if 1 depend on 2 -> put 2 first, then 1 like this
class A {
dependecy 2
dependecy 1
dependecy 3
}