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
Related
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 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 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 custom UserControl, which contains collection of custom objects.
public class Question : FrameworkElement
{
public readonly static DependencyProperty FullNameProperty =
DependencyProperty.Register("FullName", typeof(string), typeof(Question));
public readonly static DependencyProperty ShortNameProperty =
DependencyProperty.Register("ShortName", typeof(string), typeof(Question));
public readonly static DependencyProperty RecOrderProperty =
DependencyProperty.Register("RecOrder", typeof(int), typeof(Question));
public readonly static DependencyProperty AnswerProperty =
DependencyProperty.Register("Answer", typeof(string), typeof(Question));
public string FullName
{
get { return (string)GetValue(FullNameProperty); }
set { SetValue(NameProperty, value); }
}
public string ShortName
{
get { return (string)GetValue(ShortNameProperty); }
set { SetValue(ShortNameProperty, value); }
}
public string Answer
{
get { return (string)GetValue(AnswerProperty); }
set { SetValue(AnswerProperty, value); }
}
public int RecOrder
{
get { return (int)GetValue(RecOrderProperty); }
set { SetValue(RecOrderProperty, value); }
}
}
In my Control code-behind I have
public readonly static DependencyProperty QuestionsProperty =
DependencyProperty.Register("Questions", typeof(ObservableCollection<Question>), typeof(FormQuestionReportViewer),
new PropertyMetadata(new ObservableCollection<Question>()));
public ObservableCollection<Question> Questions
{
get { return GetValue(QuestionsProperty) as ObservableCollection<Question>; }
set { SetValue(QuestionsProperty, value); }
}
And in xaml markup I can define my control like this
<custom:CustomControl>
<custom:CustomControl.Questions>
<custom:Question FullName="smth text" ShortName="smth text" RecOrder="1" Answer="Yes" />
<custom:Question FullName="smth text" ShortName="smth text" RecOrder="2" Answer="Yes" />
</custom:CustomControl.Questions>
</custom:CustomControl>
It's works well, but I want to make binding my collection property in xaml like this
<custom:CustomControl>
<custom:CustomControl.Questions Items="{binding Path=Questions}">
<custom:Question FullName="{binding Name}" ShortName="{binding ShortName}" RecOrder="{binding RecOrder}" Answer={binding Answer}" />
</custom:CustomControl.Questions>
</custom:CustomControl>
How I can make that binding?
You would have to expose two separate properties, much like an ItemsControl which has an Items and ItemsSource property. It looks like you want to be able to add items using a binding and explicitly by adding to your collection. This behavior would differ from an ItemsControl, which only allows you to use the Items or ItemsSource property, but not both at the same time.
There is nothing preventing you from adding support for both ways of specifying items though, but it would be more work on your part.
First, you'd need a DependencyProperty, such as IEnumerable QuestionsSource, which you could bind to:
public readonly static DependencyProperty QuestionsSourceProperty =
DependencyProperty.Register("QuestionsSource",
typeof(IEnumerable),
typeof(FormQuestionReportViewer),
new PropertyMetadata(null));
public IEnumerable QuestionsSource
{
get { return GetValue(QuestionsSourceProperty) as IEnumerable; }
set { SetValue(QuestionsSourceProperty, value); }
}
second, you would need a regular CLR property, such as ObservableCollection<Question> Questions, which you could add items to explicitly:
private ObservableCollection<Question> questions = new ObservableCollection<Question>();
public ObservableCollection<Question> Questions
{
get { return questions; }
}
Then you could use these properties like so:
<custom:CustomControl QuestionsSource="{Binding Path=Questions}">
<custom:CustomControl.Questions>
<custom:Question FullName="{Binding Name}" ShortName="{Binding ShortName}" RecOrder="{Binding RecOrder}" Answer={Binding Answer}" />
</custom:CustomControl.Questions>
</custom:CustomControl>
The extra work comes when you want to get the full list of items. You'd need to union the two collections into a single collection. This unified collection would be exposed as a third property, which returns a read-only collection.
I am new to WPF and this is my first post. I have created a class called 'Fruit' that descends from 'DependencyObject' and adds and extra property called 'Apple'. I have created a new custom control that includes a Dependency Property called 'MyFruit' of type 'Fruit'. My question is, how can i set the default value for the properties within 'MyFruit' object (i.e. the 'Apple' property? I would like to set this in XAML using the object.
public class Gauge : Control
{
.
.
.
//---------------------------------------------------------------------
#region MyFruit Dependency Property
public Fruit MyFruit
{
get { return (Fruit)GetValue(MyFruitProperty); }
set { SetValue(MyFruitProperty, value); }
}
public static readonly DependencyProperty MyFruitProperty =
DependencyProperty.Register("MyFruit", typeof(Fruit), typeof(CircularGauge), null);
#endregion
}
//-------------------------------------------------------------------------
#region Fruit class
public class Fruit : DependencyObject
{
private int apple;
public int Apple
{
get { return apple; }
set { apple = value; }
}
}
#endregion
Instead of null in your dependency property metadata insert
new UIPropertyMetadata("YOUR DEFAULT VALUE GOES HERE")
So now it becomes
public static readonly DependencyProperty MyFruitProperty =
DependencyProperty.Register("MyFruit", typeof(Fruit), typeof(CircularGauge), new UIPropertyMetadata("YOUR DEFAULT VALUE GOES HERE"));
You need to use PropertyMetaData like this:
class MyValidation
{
public bool status
{
get { return (bool)GetValue(statusProperty); }
set { SetValue(statusProperty, value); }
}
public static readonly DependencyProperty statusProperty = DependencyProperty.Register("status", typeof(bool), typeof(MyValidation),new PropertyMetadata(false));
}