如何在 Windows 应用商店应用的代码后台中绑定自定义附加属性?使用 C#。

3

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

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异常,提示:"值不在预期范围内。"

如果我用"(Grid.Row)"替换我的属性,则不会抛出异常。

2个回答

1
进一步调查发现,如果尝试将控件ct上的附加属性Controls.StateManager.VisualState绑定到同名的附加属性上,则似乎可以在C#代码后端中运行Windows 10。
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对象作为唯一的子元素创建,它会抛出异常。


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的标记。

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

然后我可以创建一个到标记的绑定,就像这样:

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

即使使用这个技巧对我也没有用。当在一个<Binding>元素中包含自定义附加属性时,会出现WMC9999错误。 - Shahar Prish
这里似乎有一个更明确的“否”答案:https://dev59.com/J5rga4cB1Zd3GeqPs9mr 但是我找到了另一个临时解决方案。 - Anthony Wieser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接