如何从Windows商店应用程序中的代码绑定到c#中的自定义附加属性?

时间:2015-05-17 12:56:19

标签: c# xaml windows-8.1

我有一个我定义的附加属性。

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);
            }));
}
}

我可以在XAML中绑定到此属性,如下所示:

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

现在,我需要在代码后面动态地创建绑定到同一属性,所以我尝试了这个:

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

不幸的是,设置绑定的Path属性会抛出一个ArgumentException,指出:&#34; Value不在预期的范围内。&#34;

如果相反,我会替换&#34;(Grid.Row)&#34;对于我的财产,没有抛出异常。

2 个答案:

答案 0 :(得分:1)

对Windows 10的进一步研究表明,如果尝试将附加属性Controls.StateManager.VisualState绑定到控件ct上相同名称的附加属性上,这似乎在C#代码隐藏中起作用:

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);

奇怪的是,如果你没有将它包含在ResourceDictionary中,并且尝试将Binding对象创建为唯一的子对象,则抛出异常。

答案 1 :(得分:0)

为了调试这个,我想可能我的语法错误的命名空间,所以在我的xaml资源部分,我添加了这个:

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

当我检查属性路径的路径时,它与我指定的完全一样。

作为一种解决方法,我目前正从后面的代码中获得这样的绑定:

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

这似乎有效,但是为什么我不能从后面的代码创建对象?

<强>更新 这适用于Windows 8应用程序,但现在在UWP上出错。

为了让它在UWP上工作,我不得不将数据绑定到我的ParentGrid的Tag。

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

然后我可以创建一个绑定到标签,如下所示:

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