Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Default of DependencyObject

Posted on 2010-09-15
13
Medium Priority
?
649 Views
Last Modified: 2012-05-10
Dear Masters and Experts,

I'm using a CustomControl with a DependencyObject as DependencyProperty. But it seems to be impossible to set any DefaultValue in FrameworkPropertyMetadata because of an ArgumentException. Of course I could initialize the DependencyObject in the Constructor or anywhere else. But after reset this value is lost. Do You have any idea to solve this problem?

Here is an example which shows this problem:

namespace DependencyObjectDefault
{
    public class MyButton : Button
    {
        public static readonly DependencyProperty ColorSchemeProperty;
        static MyButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(typeof(MyButton)));
            try
            {
                // any ColorScheme-default results in ArgumentException
                //ColorSchemeProperty = DependencyProperty.Register("ColorScheme", typeof(ColorScheme), typeof(MyButton), new FrameworkPropertyMetadata(new ColorScheme()));
               
                // registering without default is the only possibility
                ColorSchemeProperty = DependencyProperty.Register("ColorScheme", typeof(ColorScheme), typeof(MyButton), new FrameworkPropertyMetadata());
            }
            catch (Exception e)
            {
                MessageBox.Show("ColorScheme:" + e.Message);
            }
        }
        public ColorScheme ColorScheme
        {
            get { return (ColorScheme)GetValue(ColorSchemeProperty); }
            set { SetValue(ColorSchemeProperty, value); }
        }
    }
    public class ColorScheme : DependencyObject
    {
        public static readonly DependencyProperty Brush1Property;
        public static readonly DependencyProperty Brush2Property;
        static ColorScheme()
        {
            try
            {
                Brush1Property = DependencyProperty.Register("Brush1", typeof(Brush), typeof(ColorScheme), new FrameworkPropertyMetadata(Brushes.Blue));
                Brush2Property = DependencyProperty.Register("Brush2", typeof(Brush), typeof(ColorScheme), new FrameworkPropertyMetadata(Brushes.Red));
            }
            catch (Exception e)
            {
                MessageBox.Show("ColorScheme:" + e.Message);
            }

        }
        public Brush Brush1
        {
            get { return (Brush)GetValue(Brush1Property); }
            set { SetValue(Brush1Property, value); }
        }

        public Brush Brush2
        {
            get { return (Brush)GetValue(Brush2Property); }
            set { SetValue(Brush2Property, value); }
        }
    }
}

<Window x:Class="DependencyObjectDefault.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DependencyObjectDefault"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type local:MyButton}">
            <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                <Grid>
                    <Rectangle Width="80" Height="80" Margin="0" Fill="{Binding Path=ColorScheme.Brush1,RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left" VerticalAlignment="Top"></Rectangle>
                    <Ellipse Width="80" Height="80" Margin="0" Fill="{Binding Path=ColorScheme.Brush2,RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Opacity="0.7"></Ellipse>
                </Grid>
            </Border>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <local:MyButton Content="Button" Height="125" HorizontalAlignment="Left" Margin="106,93,0,0" x:Name="myButton1" VerticalAlignment="Top" Width="119" BorderThickness="2" BorderBrush="DarkGray" Template="{StaticResource MyButtonTemplate}" Background="AliceBlue"></local:MyButton>
    </Grid>
</Window>

0
Comment
Question by:Leonard_
  • 7
  • 6
13 Comments
 
LVL 29

Accepted Solution

by:
Gautham Janardhan earned 1000 total points
ID: 33684048
inherit your ColourScheme from Freezable instead of Dependency Object and implement CreateInstabce as shown below. The you can set default values for the dependency property.
public class ColorScheme : Freezable
    {
        public static readonly DependencyProperty Brush1Property;
        public static readonly DependencyProperty Brush2Property;
        static ColorScheme()
        {
            try
            {
                Brush1Property = DependencyProperty.Register("Brush1", typeof(Brush), typeof(ColorScheme), new FrameworkPropertyMetadata(Brushes.Blue));
                Brush2Property = DependencyProperty.Register("Brush2", typeof(Brush), typeof(ColorScheme), new FrameworkPropertyMetadata(Brushes.Red));
            }
            catch (Exception e)
            {
                MessageBox.Show("ColorScheme:" + e.Message);
            }

        }
        public Brush Brush1
        {
            get { return (Brush)GetValue(Brush1Property); }
            set { SetValue(Brush1Property, value); }
        }

        public Brush Brush2
        {
            get { return (Brush)GetValue(Brush2Property); }
            set { SetValue(Brush2Property, value); }
        }

        protected override Freezable CreateInstanceCore()
        {
            return new ColorScheme();
        }
    }

Open in new window

0
 

Author Comment

by:Leonard_
ID: 33685239
Hello gauthampj,

thank you for this idea. I have to make a few tests in my much more complex application. In the example there is just the problem that after reset the sub-properties are not updated in the property-window and couldn't be changed anymore until MyButton is deselected an then selected again.

Has the default value passed to FrameworkPropertyMetadata to be same as the return value of CreateInstanceCore?

0
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33688670
no not necessarily. This will come into play only when your property has properties other than Dependency propery
0
Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

 

Author Comment

by:Leonard_
ID: 33690251
In my application I have to change the properties dynamically, but this is not possible because they are write-protected, the ColorScheme-Object is frozen. The Microsoft-Documentation tells me, that freezable objects remain unfrozen unless you explicitly freeze them. But I don't freeze the ColorScheme-Object. Is this done automatically? How can I prevent this?
0
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33693733
i don't think we can unfreeze them.. They are freezed by the runtime when the control comes into view. Instead of setting the properties of the default property it's better to reset the dependency property again with the new values...
0
 

Author Comment

by:Leonard_
ID: 33694386
I forgot to say that in my application the dynamical changes are made at designtime in a CategoryEditor, so it seems that ColorScheme-object is already frozen at designtime.

Besides I have still the problem mentioned in my first comment: after reset the sub-properties are not updated in the property-window and couldn't be changed anymore until MyButton is deselected an then selected again. After the property-window is updated this way and changing the brush by the slider in the brush-editor the brush-editor is closed immediately after a minimal change. Doing this a second time the brush could be changed this way. But the corresponding xaml-entry again didn't take place until deselecting MyButton. Could You reproduce this behavior? I'm using Visual Studio 2010.

I think Freezable is good to give a defaultvalue, but the frozen-state (if it couldn't be prevented) has some disadvantages after reset.
0
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33703886
i had tried to reproduce your scenario (but in VS2008) .. trying to attach the code here....
0
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33703925
button code
public class ButtonWithDesignTime : Button
    {
        public static readonly DependencyProperty ColorSchemeProperty;
        static ButtonWithDesignTime()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonWithDesignTime), new FrameworkPropertyMetadata(typeof(ButtonWithDesignTime)));
            try
            {
                // any ColorScheme-default results in ArgumentException
                //ColorSchemeProperty = DependencyProperty.Register("ColorScheme", typeof(ColorScheme), typeof(MyButton), new FrameworkPropertyMetadata(new ColorScheme()));

                // registering without default is the only possibility
                ColorSchemeProperty = DependencyProperty.Register("ColorScheme", typeof(ColorScheme), typeof(ButtonWithDesignTime), new FrameworkPropertyMetadata());
            }
            catch (Exception e)
            {
                MessageBox.Show("ColorScheme:" + e.Message);
            }
        }

        public ButtonWithDesignTime()
        {
            if (DesignerProperties.GetIsInDesignMode(this))
            {
                Content = "I'm in design mode";
            }
        }

        public ColorScheme ColorScheme
        {
            get { return (ColorScheme)GetValue(ColorSchemeProperty); }
            set { SetValue(ColorSchemeProperty, value); }
        }
    }

    public class ColorScheme : Freezable
    {
        public static readonly DependencyProperty Brush1Property;
        public static readonly DependencyProperty Brush2Property;
        static ColorScheme()
        {
            try
            {
                Brush1Property = DependencyProperty.Register("Brush1", typeof(Brush), typeof(ColorScheme), new FrameworkPropertyMetadata(Brushes.Blue));
                Brush2Property = DependencyProperty.Register("Brush2", typeof(Brush), typeof(ColorScheme), new FrameworkPropertyMetadata(Brushes.Red));
            }
            catch (Exception e)
            {
                MessageBox.Show("ColorScheme:" + e.Message);
            }

        }
        public Brush Brush1
        {
            get { return (Brush)GetValue(Brush1Property); }
            set { SetValue(Brush1Property, value); }
        }

        public Brush Brush2
        {
            get { return (Brush)GetValue(Brush2Property); }
            set { SetValue(Brush2Property, value); }
        }

        protected override Freezable CreateInstanceCore()
        {
            return new ColorScheme();
        }
    }

Open in new window

0
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33703939
metadata file

.. this code is working as expected...the changes made in the property editor are reflecting in the xaml
internal class Metadata : IRegisterMetadata {

        // Called by Cider to register any design-time metadata
        public void Register() {
            AttributeTableBuilder builder = new AttributeTableBuilder();

            // Adorners
            builder.AddCustomAttributes(typeof(ButtonWithDesignTime), new FeatureAttribute(typeof(OpacitySliderAdornerProvider)));
            builder.AddCustomAttributes(typeof(ButtonWithDesignTime), new FeatureAttribute(typeof(PopupButtonAdornerProvider)));

            // MenuActions
            builder.AddCustomAttributes(typeof(ButtonWithDesignTime), new FeatureAttribute(typeof(CustomContextMenuProvider)));
            MetadataStore.AddAttributeTable(builder.CreateTable());
        }
    }

Open in new window

0
 

Author Comment

by:Leonard_
ID: 33707474
I'm sorry, I'm a little bit confused about the Metadata and the differences between VS 2008 and VS 2010. I'm using Metadata implementing Microsoft.Windows.Design.Metadata.IProvideAttributeTable. MetadataStore and IRegisterMetadata are only available in VS 2008. I'll try to translate your code to VS 2010.

But what about the types passed to FeatureAttribute? I found a similar example only in VS 2008. Besides the Brush-Editor is complete different in VS 2010 and it's color-sliders are already build-in.
0
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 33707736
sorry i wont be able to test this in 2010 at this moment. What ever i'm are passing to the feature attributes you need to replace it with your designer.Please try to convert it into vs2010 and let me know hos it goes
0
 

Author Comment

by:Leonard_
ID: 33742140
I had no success with the feature attributes. But I think the problem in the Brush-Editor is not a problem of Freezable as the same behavior after reset occurs if ColorScheme implements INotifyPropertyChanged (which also allows a default-value). If there is no corresponding xaml-entry of the ColorSchemeObject (after reset) it is not possible to change the Brush with the slider. But I accept Freezable as solution to register a default-value of a DependencyObject.
0
 

Author Closing Comment

by:Leonard_
ID: 33742176
Problems in Visual Studio 2010 after reset:

The sub-properties are not updated in the property -window.

It is not possible to use the Brush-slider as it is immediately closed after a minimal change.
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
High user turnover can cause old/redundant user data to consume valuable space. UserResourceCleanup was developed to address this by automatically deleting user folders when the user account is deleted.
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Loops Section Overview

916 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question