How to use a custom class in XAML? - wpf

I have the following class,
internal class PageInformation
{
public string Name
{
get;
set;
}
public Uri PageUri
{
get;
set;
}
}
How can I use it in XAML (a page) and assign values to its properties?
Update-1:
I added xmlns attribute in page tag
<Page xmlns:local="clr-namespace:Demo.Pages">
and inherited PageInformation from DependencyObject (to have dependency properties).
Still XAML does not recognize the PageInformation class

I was trying to use PageInformation element in a Canvas. Since it is not a UIElement, I think, It can't be added there.
I can use it as a resource element instead (in Page.Resources) :)

Related

Custom markupextension on custom DataTemplate property

I'm wondering if there is a way to use a custom markup extension on a custom property on a type derived from datatemplate?
I need some additional information inside my DataTemplates:
public class MyDataTemplate : DataTemplate
{
public string GroupName { get; set; }
public string TemplateKey { get; set; }
public object Geometry { get; set; }
}
<MyDataTemplate x:Key="Foo" DataType="{x:Type system:String}" GroupName="Group1"
Geometry="{telerik:CommonShape ShapeType=RectangleShape}">
...
</MyDataTemplate>
When I put the CommonShape markupextension on the DataType property, everything works.
When I put the x:Type markupextension on the Geometry property, everything works, too.
But if I put the custom markupextension on the custom property, I get the error
The property 'Geometry' cannot be set as a property element on template.
Only Triggers and Storyboards are allowed as property elements.
Is there any workaround for this?
Alex
Edit:
One possible workaround could be to put the values of the markupextension into the resource dictionary and use a StaticResource on the Geometry property - however, I'm not sure if this is possible using xaml?

Binding to observable collection, dependency property fails

I have a usercontrol where I need a list of a simple class I've made, called Person:
public class Person {
public string Name { get; set; }
}
Now in the usercontrol, I need to have a ObservableCollection<Person> that I can bind to. So I figure I need to make it a dependency property. So in the usercontrol I have the following:
public static readonly DependencyProperty PersonsDependencyProperty =
DependencyProperty.Register("Persons", typeof(ObservableCollection<Person>),
typeof(PersonUserControl));
And the property is like this:
public ObservableCollection<Person> Persons
{
get
{
return (ObservableCollection<Person>)GetValue(PersonsDependencyProperty);
}
set
{
SetValue(PersonsDependencyProperty, value);
}
}
Now in my MainWindow.xaml codebehind I make an ObservableCollection<Person> called PersonList, set the mainwindow datacontext to self, and bind to it like so:
<Local:PersonUserControl Persons="{Binding PersonList}">
</Local:PersonUserControl>
And I get the error: Exception has been thrown by the target of an invocation. - No further explanation. Can anybody tell me how to react to it or what I'm doing wrong.
I hope I'm being clear enough.
PersonsDependencyProperty should be just PersonsProperty. Hard to say whether that's the underlying cause without more information, but that's certainly a problem. WPF appends "Property" onto the binding path in order to find the related dependency property. Thus, it won't find yours.

Tying user control property to named parent property

I want to set a user control property to the value of a property in a parent control. For example, let's say my main window control has some initial configuration data. Currently I use the following in XAML:
<Window x:Class="MyProject.MainWindow"
x:Name="TopWindow" ... >
...
<local:MyUserControl Config="{Binding ElementName=TopWindow,
Path=MyUserControlConfig, Mode=OneTime}" />
</Window>
But this appears to require two dependency properties, one in the MainWindow (MyUserControlConfig):
namespace MyProject
{
public partial class MainWindow: Window
{
public static readonly DependencyProperty MyUserControlConfigProperty=
DependencyProperty.Register("MyUserControlConfig",
typeof(UserControlConfig), typeof(MainWindow));
public UserControlConfig MyUserControlConfig
{
get { return (UserControlConfig)
GetValue(MyUserControlConfigProperty); }
set { SetValue(MyUserControlConfigProperty, value); }
}
}
}
and one in MyUserControl (Config):
namespace MyProject
{
public partial class MyUserControl: UserControl
{
public static readonly DependencyProperty ConfigProperty=
DependencyProperty.Register("Config",
typeof(UserControlConfig), typeof(MainWindow));
public UserControlConfig Config
{
get { return (UserControlConfig) GetValue(ConfigProperty); }
set { SetValue(ConfigProperty, value); }
}
}
}
I really don't need to observe any changes, just to pass data into my user control at the time of creation. Is this possible to do using simple properties for at least one of the two or must I use two dependency properties to perform this (one time) initialization?
Update: Jay's solution leaves us with just a CLR property in the MainWindow class:
namespace MyProject
{
public partial class MainWindow: Window
{
public UserControlConfig MyUserControlConfig {get; private set;}
...
}
}
Now if it was just possible to remove the dependency property from the MyUserControl class and replace it with a simple property that still gets initialized via XAML binding (or some other XAML mechanism, so I can pass in the data source via XAML).
I could be mistaken, but if you can bind to CLR properties on other classes, I'd expect you could bind to a CLR proprety on your MainWindow class.
Have you tried that?

HierarchicalDataTemplate Link By Parent

I want bind my treeview. There are a lot of samples binding treeview by object, which contains children collection. I've got domain having just Parent pointer.
public class Service : BaseDomain
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual Service Parent { get; set; }
}
Can I bind collection of this objects to my treeView. Thanks
It's not possible with HierarchicalDataTemplate, but you could create custom convertedr for ItemsSource binding. In general case converting such structure to tree might be resource intensive task (particularly it requires that treeview grabs all your data before displaying tree root).

Can I use XAML to set a nested property (property of the value of a property) of a control?

I've got a WPF Control that exposes one of it's children (from it's ControlTemplate) through a read-only property. At the moment it's just a CLR property, but I don't think that makes any difference.
I want to be able to set one of the properties on the child control from the XAML where I'm instantiating the main control. (Actually, I would like to bind to it, but I think setting it would be a good first step.)
Here's some code:
public class ChartControl : Control
{
public IAxis XAxis { get; private set; }
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.XAxis = GetTemplateChild("PART_XAxis") as IAxis;
}
}
public interface IAxis
{
// This is the property I want to set
double Maximum { get; set; }
}
public class Axis : FrameworkElement, IAxis
{
public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(Axis), new FrameworkPropertyMetadata(20.0, FrameworkPropertyMetadataOptions.AffectsRender, OnAxisPropertyChanged));
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
}
Here's the two ways I can think of setting the nested property in XAML (neither compile):
<!--
This doesn't work:
"The property 'XAxis.Maximum' does not exist in XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'."
"The attachable property 'Maximum' was not found in type 'XAxis'."
-->
<local:ChartControl XAxis.Maximum="{Binding Maximum}"/>
<!--
This doesn't work:
"Cannot set properties on property elements."
-->
<local:ChartControl>
<local:ChartControl.XAxis Maximum="{Binding Maximum}"/>
</local:ChartControl>
Is this even possible?
Without it I guess I'll just need to expose DP's on the main control that get bound through to the children (in the template). Not so bad, I guess, but I was just trying to avoid an explosion of properties on the main control.
Cheers.
You can't do it like this... you can access nested properties through its path in a binding, but not when you define the value of the property.
You have to do something like that :
<local:ChartControl>
<local:ChartControl.XAxis>
<local:Axis Maximum="{Binding Maximum}"/>
</local:ChartControl.XAxis>
</local:ChartControl>

Resources