How can I bind to a custom attached property in c# from code behind in a windows store app?

人走茶凉 提交于 2019-12-23 16:13:41

问题


I have an attached property I defined.

namespace Controls
{
public class StateManager : DependencyObject
{
    public static string GetVisualState(DependencyObject obj)
    {
        return (string)obj.GetValue(VisualStateProperty);
    }

    public static void SetVisualState(DependencyObject obj, string value)
    {
        obj.SetValue(VisualStateProperty, value);
    }

    // Using a DependencyProperty as the backing store for VisualStateProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty VisualStateProperty =
        DependencyProperty.RegisterAttached("VisualState", typeof(string), typeof(StateManager),
        new PropertyMetadata(null,
            (s, e) => {
                var stateName = (string)e.NewValue;
                var ctrl = s as Control;
                if (ctrl == null) throw new InvalidCastException("You can only attach VisualState properties to Controls");

                if (!string.IsNullOrEmpty(stateName))
                    VisualStateManager.GoToState(ctrl, stateName, true);
            }));
}
}

I can bind to this property in XAML Like this:

<controls:TitleStrip
    controls:StateManager.VisualState=
          "{Binding (controls:StateManager.VisualState), ElementName=pageRoot}" 
    Grid.Column="1"/>

Now, I need to create a binding dynamically in code behind to the same property, so I tried this:

var pp = new PropertyPath("(controls:StateManager.VisualState)");
var binding = new Binding() { Path= pp, Source=this };
BindingOperations.SetBinding(ct, StateManager.VisualStateProperty, binding);

Unfortunately, setting the Path property of the binding, throws an ArgumentException stating: "Value does not fall within the expected range."

If instead, I substitute "(Grid.Row)" for my property, no exception is thrown.


回答1:


Further investigation on windows 10 shows that this appears to work in C# codebehind, if trying to bind to the attached property Controls.StateManager.VisualState onto the Attached Property of the same name on the control ct:

string bindingxaml =
@"<ResourceDictionary
xmlns:controls=""using:Controls""
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
>
<Binding x:Key=""binding"" Path=""(controls:StateManager.VisualState)"" />
</ResourceDictionary>";

ResourceDictionary dict = XamlReader.Load(bindingxaml) as ResourceDictionary;
Binding binding = dict["binding"] as Binding;
binding.Source = this;
BindingOperations.SetBinding(ct, StateManager.VisualStateProperty, binding);

Strangely, this throws exceptions if you don't enclose it in a ResourceDictionary, and try to create the Binding object as the only child.




回答2:


To debug this, I thought maybe my syntax was wrong for the namespace, so in my xaml resources section, I added this:

<Binding x:Key="yuck" Path="(controls:StateManager.VisualState)" ElementName="pageRoot" />

When I examined the Path of the property path, it was exactly as I specified it.

As a workaround, I'm currently getting the binding like this from code behind:

BindingOperations.SetBinding(ct, StateManager.VisualStateProperty, 
    Resources["yuck"] as Binding);

This appears to be working, however why can't I create the object from code behind?

Update This worked on Windows 8 apps, but now gives errors on UWP.

To get it to work on UWP, I had to databind to the Tag of my ParentGrid.

<Grid x:Name="ParentGrid" Tag="{Binding ElementName=pageRoot, Path=(controls:StateManager.VisualState)}">

Then I can create a Binding to the Tag, like this:

var pp3 = new PropertyPath("Tag");
barf = new Binding() { Path = pp3, Source = ParentGrid };


来源:https://stackoverflow.com/questions/30287091/how-can-i-bind-to-a-custom-attached-property-in-c-sharp-from-code-behind-in-a-wi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!