Can I create XAML properties like in the "x" namespace - wpf

I know that I can make attached properties, for example
public enum HideOption
{
node,
tree
}
public static class Hide
{
public static readonly DependencyProperty OptionProperty
= DependencyProperty.RegisterAttached ( "Option",
typeof(HideOption),
typeof(Hide),
new PropertyMetadata(HideOption.node) ) ;
public static HideOption GetOption ( DependencyObject obj )
{
return (HideOption)obj.GetValue(OptionProperty);
}
public static void SetOption ( DependencyObject obj, HideOption value )
{
obj.SetValue(OptionProperty, value);
}
}
and use it on XAML nodes, like
<Grid m:Hide.Option="tree">
</Grid>
The attributes in the "x" namespace have a shorter syntax, like
<Grid x:Uid="MyGrid">
</Grid>
Is it possible to create my own attributes which would use this syntax, for example
<Grid m:Hide="tree">
</Grid>
or is it some special feature of the XAML Language not available to normal libraries?

This are not attached properties. The x namespace contains XAML compiler directives. They are instructions to the XAML parser and compiler or code generator. Like x:Class tells the compiler to link the generated XAML class with a partial declared C# class (code-behind). This directives are no DependencyProperties and don't participate in the dependency property system like attached properties do.
Since this directives are compiler level, I don't think that you can create them. You would need a way to tell the compiler how to interpret this directives.

Related

WPF Dependency Object

Has anyone ever heard of implementing IDependencyObject instead of inheriting from it -- that way one could actually create a class hierarchy instead of having to use only interfaces when trying to get both dependency object/property and custom behavior on our classes.
I want to have a hierarchy of class kinds that are directly usable in the context of an existing structure, i.e. Polygon. I want to be able to use my PolyType in any place, and without any more dialogue and indirection that would be required if I place the PolyGon existing type as a Part of my DependencyObject. But I also want to be able to have my class as the a) the target of {Binding} markup extension, b) Animate properties of PolyType and c) apply themed styling to PolyType.
I want to implement IDependencyObject instead of being forced to inherit from it directly, and obstructing my ability to be a direct descendent and usable in place of, PolyGon.
Not sure why you have to inherit from DependencyObject. I use a custom code snippet that generates the following code to register a dependancy property:
public partial class UserControl1 : UserControl
{
public static DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyProperty", typeof(Polygon), typeof(UserControl1), new FrameworkPropertyMetadata(new PropertyChangedCallback(MyProperty_Changed)));
public Polygon MyProperty
{
get { return (Polygon)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
private static void MyProperty_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
UserControl1 thisClass = (UserControl1)o;
thisClass.SetMyProperty();
}
private void SetMyProperty()
{
//Put Instance MyProperty Property Changed code here
}
public UserControl1()
{
InitializeComponent();
}
}
As you can see the DependencyObject can be any type of object. If this is not what you need, please post you code examples, or explain your situation better.

MVVM: How to convert this code behind snippet into an AttachedProperty?

In WPF, I would like to know how to convert code behind into an attached behavior, as this follows the MVVM pattern and is more maintainable and testable.
I have the following xAML which implements a docking manager:
<dxb:BarManager x:Name="MyBarManager"/>
In code behind, I could save the layout to an XML file:
MyBarManager.SaveLayoutToStream(...);
I can also load the layout from an XML file:
MyBarManager.LoadLayoutFromStream(...);
In order to follow the MVVM pattern, I would like to convert this to an attached property, so instead of having code behind, I could bind to a string Test in the ViewModel:
<!-- BarManager is part of the framework, it has methods to save/load layout. -->
<dxb:BarManager x:Name="MyBarManager"
attached:BarLayoutManagerAttachedProperty.DockLayoutSerialize="{Binding Test}">
What I have tried so far
I used the ReSharper template "dependencyProperty" to create the following attached property, however, there doesn't seem to be a way to hook up any of the calls:
public class BarLayoutManagerAttachedProperty : DependencyObject
{
public static readonly DependencyProperty DockLayoutSerializeProperty = DependencyProperty.RegisterAttached(
"DockLayoutSerialize",
typeof (BarManager),
typeof (BarLayoutManagerAttachedProperty),
new PropertyMetadata(default(BarManager)));
public static void SetDockLayoutSerialize(DependencyObject element, BarManager value)
{
element.SetValue(DockLayoutSerializeProperty, value);
}
public static BarManager GetDockLayoutSerialize(DependencyObject element)
{
return (BarManager) element.GetValue(DockLayoutSerializeProperty);
}
}

Are CLR wrappers for dependency properties optional or not?

I was under the impression that CLR wrappers for dependency properties were optional under WPF, and just useful for setting within your own code.
However, I have created a UserControl without wrappers, but some XAML that uses it will not compile without them:
namespace MyControlLib
{
public partial class MyControl : UserControl
{
public static readonly DependencyProperty SomethingProperty;
static MyControl()
{
SomethingProperty = DependencyProperty.Register("Something", typeof(int), typeof(MyControl));
}
}
}
XAML usage:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:MyControlLib;assembly=MyControlLib">
<ctrl:MyControl Something="45" />
</Window>
Trying to compile this gives:
error MC3072: The property 'Something' does not exist in XML namespace 'clr-namespace:MyControlLib'. Line blah Position blah.
Adding a CLR wrapper in MyControl.xaml.cs like:
public int Something
{
get { return (int)GetValue(SomethingProperty); }
set { SetValue(SomethingProperty, value); }
}
means it all compiles and works fine.
What am I missing?
You could use dependency properties without wrappers inside runtime bindings, but to set the property like you want you must have C# property to allow xaml compiler to compile your code.
I believe it will compile without the wrappers if you specify the namespace prefix on the property.
They are optional, but without them the property does not show up in the XAML designer automatically
<ctrl:MyControl ctrl:MyControl.Something="45" />

How to Add Custom Silverlight XAML Attributes?

Is it possible to introduce 'custom' attributes into different UI Elements in XAML ? Also to read them later like we add attributes for server controls in ASP.NET ?
I intend to read specific attributes and operate on them together.
It sounds like you're trying to find Attached Properties.
An attached property lets you add in a property, definable in Xaml, which can be "attached" to any UIelement. You then retrieve them in code like any other Dependency Property.
Here is the approach I tend to take with this.
Create a new class file called Meta:-
namespace SilverlightApplication1
{
public static class Meta
{
#region SomeValue
public static string GetSomeValue(DependencyObject obj)
{
return (string)obj.GetValue(SomeValueProperty);
}
public static void SetSomeValue(DependencyObject obj, string value)
{
obj.SetValue(SomeValueProperty, value);
}
public static readonly DependencyProperty SomeValueProperty =
DependencyProperty.RegisterAttached("SomeValue", typeof(string), typeof(Meta),
new PropertyMetadata(null));
#end region
#region SomeOtherValue
// Boilerplate code from above.
#end region
}
}
A value can now be attached in XAML like this:-
<TextBox x:Name="txt" local:Meta.SomeValue="Hello, World!" />
At some point in code this value can be retrieved with:-
string value = Meta.GetSomeValue(txt);
Note you don't have to stick with String as the type of the property you can pretty much use any type you like with the limitation that if you can to attach it in XAML the type must be compatible with the way XAML constructs objects (for example requires a default constructor).
The way I've accomplished that is by creating a new class that inherits the base control.
For example, I have a class called WebTextBox that inherits TextBox. And inside WebTextBox are some custom properties and events. By doing this you're inheriting all the behaviors of the TextBox control. But you can get creative here if you choose, even modifying the behavior by overriding events and such.
Anyway, after you create the class you'll then have to add the namespace for the project to the XAML. Something like this:
xmlns:me="clr-namespace:YourNamespace;assembly=YourAssembly"
And then you can add a WebTextBox (or whatever you call it) like this:
<me:WebTextBox CustomAttribute="cool stuff" />

DepedencyProperty within a MarkupExtension

Is it possible to have a DependencyProperty within a MarkupExtension derived class?
public class GeometryQueryExtension : MarkupExtension
{
public XmlDataProvider Source { get; set; }
public string XPath { get; set; }
public static readonly DependencyProperty ArgumentProperty = DependencyProperty.RegisterAttached(
"Argument",
typeof(string),
typeof(GeometryQueryExtension)); // this wont work because GeometryQueryExtension is not a DependencyProperty
public string Argument
{
get
{
return (string)GetValue(ArgumentProperty); // this wont even compile because GeometryQueryExtension doesnt derive from a class which has GetValue
}
set
{
SetValue(ArgumentProperty,value);// this wont even compile because GeometryQueryExtension doesnt derive from a class which has SetValue
}
}
}
The extension is used in the following snippet.
<Label.Content>
<local:GeometryQueryExtension Source="{StaticResource shapesDS}">
<local:GeometryQueryExtension.XPath>
/Shapes/Geometry/{0}
</local:GeometryQueryExtension.XPath>
<local:GeometryQueryExtension.Argument>
<Binding XPath="Geometry"/> <!-- will throw exception when processing this bind -->
</local:GeometryQueryExtension.Argument>
</local:GeometryQueryExtension>
</Label.Content>
Is it even possible to build such an extension or am i just barking up the wrong tree ?
(the code above wont compile and run, but i posted it here to best illustrate the problem).
No, you can only add dependency properties to classes that are derived from DependencyObject, MarkupExtention is derived directly from Object
Yea.. it’s an ugly problem.. However it has a simple non intuitive answer.
Create another markup extension to get the static resource.
So instead of using {StaticResource shapesDS}
You would create a new MarkupExtension called DataSetLocator
I'm not going to write the code but the Provide value would need to return your dataset based on a name or some other input.
Then you change your xaml to have your extension use the dataset locator extension example Source="{DataSetLocator name=shapesDS }"
It’s too bad that extensions don’t extend DependencyProperty but they don’t.
Just use IMarkupExtension instead of MarkupExtension and you can extend DependencyObject. At least in Silverlight 5 you can, but I would assume WPF also has it.

Resources