Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 652
  • Last Modified:

Default of DependencyObject

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
Leonard_
Asked:
Leonard_
  • 7
  • 6
1 Solution
 
Gautham JanardhanCommented:
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
 
Leonard_Author Commented:
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
 
Gautham JanardhanCommented:
no not necessarily. This will come into play only when your property has properties other than Dependency propery
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
Leonard_Author Commented:
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
 
Gautham JanardhanCommented:
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
 
Leonard_Author Commented:
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
 
Gautham JanardhanCommented:
i had tried to reproduce your scenario (but in VS2008) .. trying to attach the code here....
0
 
Gautham JanardhanCommented:
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
 
Gautham JanardhanCommented:
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
 
Leonard_Author Commented:
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
 
Gautham JanardhanCommented:
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
 
Leonard_Author Commented:
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
 
Leonard_Author Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now