Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
DependencyProperty ClearValue
Message
De
23/02/2009 08:53:58
 
 
À
23/02/2009 02:12:51
Information générale
Forum:
ASP.NET
Catégorie:
Windows Presentation Foundation (WPF)
Versions des environnements
Environment:
C# 3.0
Divers
Thread ID:
01381612
Message ID:
01383454
Vues:
28
>>>>Fire away (g) - but, AFAICS, my current solution is working (well, I haven't been able to break it yet - i.e. end up with a element where the property is explicitly false).
>>>>
>>>>Oh - and note that when using an attached property the same logic applies to nested elements other than ShapeCanvas3.
>>>>Best,
>>>>Viv
>>>
>>>I may have coded it diferently than you did.
>>>
>>>No rush on my part, but you might want to take a look when you get some time.
>>
>>Hi,
>>I tried your version. Below is a modified version that I worked with ( I made the form a bit more complex, added SetContentIsLocked() and GetContentIsLocked() and changed the debug writes a bit. AFAICS the Coerce callback was actually messing things up and, for my purposes at least, was not neccessary. It's still there at the moment so that I can trace when it is actually called. You'll notice that I've set the ContentIsLocked property on some of the elements in XAML and you can see these being set at startup in the debug window. Also, AFAICS the Coerce method is only called on properties that are unset. Anyway try this:
>>
<Window x:Class="WpfPropertyInheritance.Window1"
>>    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
>>    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>>    xmlns:loc="clr-namespace:WpfPropertyInheritance"
>>    Title="Window1" Height="300" Width="504">
>>    <StackPanel>
>>        <StackPanel Orientation="Horizontal">
>>            <Button  Name="button1" Click="button1_Click">Lock Outer</Button>
>>            <Button  Name="button2"  Click="button2_Click">Unlock Outer</Button>
>>            <Button  Name="button3" Click="button3_Click">Lock Inner</Button>
>>            <Button  Name="button4" Click="button4_Click">Unlock Inner</Button>
>>            <Button Height="23" Name="button6" Width="75" Click="button6_Click">Lock R3</Button>
>>            <Button Height="23" Name="button5" Width="75" Click="button5_Click">Unlock R3</Button>
>>        </StackPanel>
>>        <StackPanel>
>>            <Label Content="{Binding ElementName=scTest,Path=ContentIsLocked}" ></Label>
>>            <Label Content="{Binding ElementName=InnerShapeCanvas3,Path=ContentIsLocked}" ></Label>
>>            <loc:ShapeCanvas3 x:Name="scTest" Height="172">
>>                <StackPanel Canvas.Left="46" Canvas.Top="38" Height="100" x:Name="spnlTest" Width="200" >
>>                    <Rectangle Height="100" x:Name="rectangle1" Stroke="Black" Width="250" Fill="Azure" loc:ShapeCanvas3.ContentIsLocked="false"/>
>>                    <loc:ShapeCanvas3 x:Name="InnerShapeCanvas3">
>>                        <Rectangle Height="100" x:Name="rectangle3" Stroke="Black" Width="250" Fill="Azure" loc:ShapeCanvas3.ContentIsLocked="true" />
>>                        <Rectangle Height="100" x:Name="rectangle4" Stroke="Black" Width="250" Fill="Azure" loc:ShapeCanvas3.ContentIsLocked="false"/>
>>                    </loc:ShapeCanvas3>
>>                    <Rectangle Height="100" x:Name="rectangle2" Stroke="Black" Width="200" Fill="Azure" />
>>                </StackPanel>
>>            </loc:ShapeCanvas3>
>>        </StackPanel>
>>    </StackPanel>
>></Window>
>>
and
using System.Windows;
>>using System.Windows.Controls;
>>using System.Diagnostics;
>>
>>namespace WpfPropertyInheritance
>>{
>>    /// <summary>
>>    /// Interaction logic for Window1.xaml
>>    /// </summary>
>>    public partial class Window1 : Window
>>    {
>>        public Window1()
>>        {
>>            InitializeComponent();
>>        }
>>
>>        private void button1_Click(object sender, RoutedEventArgs e)
>>        {
>>            Debug.WriteLine("**************************");
>>            Debug.Indent();
>>            Debug.WriteLine("Setting outer to True");
>>            scTest.ContentIsLocked = true;
>>            Debug.Unindent();
>>            Debug.WriteLine("*********End*********");
>>        }
>>
>>        private void button2_Click(object sender, RoutedEventArgs e)
>>        {
>>            Debug.WriteLine("**************************");
>>            Debug.Indent();
>>            Debug.WriteLine("Setting outer to False");
>>            scTest.ContentIsLocked = false;
>>            Debug.Unindent();
>>            Debug.WriteLine("*********End*********");
>>        }
>>
>>        private void button3_Click(object sender, RoutedEventArgs e)
>>        {
>>            Debug.WriteLine("**************************");
>>            Debug.Indent();
>>            Debug.WriteLine("Setting inner to True");
>>            InnerShapeCanvas3.ContentIsLocked = true;
>>            Debug.Unindent();
>>            Debug.WriteLine("*********End*********");
>>        }
>>
>>        private void button4_Click(object sender, RoutedEventArgs e)
>>        {
>>            Debug.WriteLine("**************************");
>>            Debug.Indent();
>>            Debug.WriteLine("Setting inner to False");
>>            InnerShapeCanvas3.ContentIsLocked = false;
>>            Debug.Unindent();
>>            Debug.WriteLine("*********End*********");
>>        }
>>
>>        private void button5_Click(object sender, RoutedEventArgs e)
>>        {
>>            ShapeCanvas3.SetContentIsLocked(rectangle3, false);
>>        }
>>
>>        private void button6_Click(object sender, RoutedEventArgs e)
>>        {
>>            ShapeCanvas3.SetContentIsLocked(rectangle3, true);
>>        }
>>    }
>>
>>    public class ShapeCanvas3 : Canvas
>>    {
>>        public static DependencyProperty ContentIsLockedProperty;
>>
>>        static ShapeCanvas3()
>>        {
>>            FrameworkPropertyMetadata p = new FrameworkPropertyMetadata(
>>              new PropertyChangedCallback(OnContentIsLockedChanged),
>>              new CoerceValueCallback(CoerceIsLocked)
>>              );
>>            p.Inherits = true;
>>            ContentIsLockedProperty = DependencyProperty.RegisterAttached("ContentIsLocked", typeof(bool), typeof(ShapeCanvas3), p);
>>        }
>>
>>        public static void SetContentIsLocked(FrameworkElement element, bool value)
>>        {
>>            Debug.WriteLine("SetContentIsLocked to " + value.ToString() + " on " + element.Name);
>>            element.SetValue(ContentIsLockedProperty, value);
>>
>>            //Property is not changed anyway if false so this option doesn't make any difference:
>>            //if (value)
>>            //    element.SetValue(ContentIsLockedProperty, value);
>>            //else
>>            //    element.SetValue(ContentIsLockedProperty, DependencyProperty.UnsetValue);
>>        }
>>
>>        public static bool GetContentIsLocked(FrameworkElement element)
>>        {
>>            Debug.WriteLine("GetContentIsLocked for " + element.Name);
>>            return (bool)element.GetValue(ContentIsLockedProperty);
>>        }
>>
>>        public bool ContentIsLocked
>>        {
>>            set
>>            {
>>                if (value)
>>                {
>>                    Debug.WriteLine("ContentIsLocked.SetValue to true");
>>                    SetValue(ContentIsLockedProperty, value);
>>                }
>>                else
>>                {
>>                    Debug.WriteLine("ContentIsLocked.SetValue to unset");
>>                    this.ClearValue(ContentIsLockedProperty);
>>                }
>>            }
>>            get { return (bool)GetValue(ContentIsLockedProperty); }
>>        }
>>
>>        private static void OnContentIsLockedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
>>        {
>>            Debug.WriteLine("ContentIsLockedChanged on " + ((FrameworkElement)obj).Name + " from " + e.OldValue.ToString() + " to " + e.NewValue.ToString());
>>        }
>>
>>        private static object CoerceIsLocked(DependencyObject d, object value)
>>        {
>>            Debug.WriteLine("--------");
>>            Debug.Indent();
>>            Debug.WriteLine("Coerce called for " + ((FrameworkElement)d).Name);
>>            Debug.WriteLine("Current Value is " + d.ReadLocalValue(ContentIsLockedProperty).ToString());
>>            Debug.WriteLine("Requested value is " + value.ToString());
>>            Debug.Unindent();
>>            Debug.WriteLine("--------");
>>            return value;
>>            //This actually messes things up!
>>            //return (bool)value ? value : DependencyProperty.UnsetValue;
>>        }
>>    }
>>}
>>
Best,
>>Viv
>
>That works for the shape canvas. But if I press Unlock R3 with the ShapeCanvas Locked, R3 does get set to False.
>
>To reproduce:
>
>Start Program
>Lock Outer
>Unlock R3
>
>Result:
>ContentIsLockedChanged on rectangle3 from True to False
>
>If I uncoment this it does not get set to false:
>
>
            //Property is not changed anyway if false so this option doesn't make any difference:
>            if (value)
>                element.SetValue(ContentIsLockedProperty, value);
>            else
>                element.SetValue(ContentIsLockedProperty, DependencyProperty.UnsetValue);
>
>Did you really want to comment that off?

Duh. No - of course it does need to be there.

>
>Even with that fix the method I used in my code to set the property will still set it to false and since that's the same call xaml uses, so will the xaml. The only work around I know for that is to make ContentIsLocked readonly, but then you won't be able to set it from xaml :-(

AFAICS the only place to trap and handle this is in the Coerce callback. But I was still confused as to the result of returning DependencyProperty.UnSetValue from this. I now see that this just leaves the old value in place rather than being the equivalent of .ClearValue() which is what I need. But so far I don't see how I can achieve the latter within the callback method .......
Best,
Viv
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform