XAML 将对象指派给ResourceDictionary中的BindableProperty

um6iljoc  于 2022-12-07  发布在  其他
关注(0)|答案(2)|浏览(100)

I try to initialize and assign an instance of a custom class to a BindableProperty in a ResourceDictionary (styles.xaml).
My class:

namespace Foo {
  public class Colors {
    public Color Positive { get; set; }
    public Color Negative { get; set; }
    public Color Neutral { get; set; }

    public Colors() { }
  }
}

My class with BindableProperty:

namespace Foo {
  public class Bar : ContentView {
    public Colors Colors {
      get => (Colors)GetValue(ColorsProperty);
      set => SetValue(ColorsProperty, value);
    }

   public static BindableProperty ColorsProperty = 
            BindableProperty.Create(nameof(Colors), typeof(Colors), 
            typeof(Bar), null, BindingMode.OneWay);

styles.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:foo="clr-namespace:Foo;assembly=Foo">
  <foo:Colors
        x:Key="colors"
        Positive="Green"
        Negative="Red"
        Neutral="Blue"/>

  ...

  <Style TargetType="foo:Bar">
    <Setter Property="Colors" Value="{StaticResource colors}"/>
  </Style>
</ResourceDictionary>

A breakpoint in the constructor of class Foo.Colors is hit, so an instance of this class is created during loading styles.xaml. However loading styles.xaml crashes with an unhandled NullReferenceException inside Mono.Android. When i delete the assignment of the Color-Property everything works fine, so the assignment must be the problem.
Any suggestions?
Exception Details:

System.NullReferenceException: Object reference not set to an instance of an object.
  at Android.Runtime.JNINativeWrapper._unhandled_exception (System.Exception e) [0x0000e] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:12 
  at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V (_JniMarshal_PPL_V callback, System.IntPtr jnienv, System.IntPtr klazz, System.IntPtr p0) [0x0001d] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:111 
  at (wrapper native-to-managed) Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(intptr,intptr,intptr)

The Exception occures in App.xaml.g.cs, after global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(App));

8nuwlpux

8nuwlpux1#

我找到了一个适合我的简单解决方案:
在styles.xaml中,我将StaticResource替换为DynamicResource

<Style TargetType="foo:Bar">
  <Setter Property="Colors" Value="{DynamicResource colors}"/>
</Style>

感谢所有的建议!

1tu0hz3e

1tu0hz3e2#

您似乎想要使用独立的资源字典。过去,当我遵循Microsoft的相关文件时,我在使用这些资源字典时遇到过问题。我总是必须将字典设定成在另一个组件中:
styles.xaml:

<ResourceDictionary
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:foo="clr-namespace:DELETEME"
    x:Class="DELETEME.styles">

    <foo:Colors
        x:Key="colors"
        Positive="Green"
        Negative="Red"
        Neutral="Blue"/>

    <Style TargetType="foo:Bar">
        <Setter Property="Colors" Value="{StaticResource colors}"/>
    </Style>
</ResourceDictionary>

请注意,此文件确实需要一个简单的代码:

namespace DELETEME
{
    public partial class styles : ResourceDictionary
    {
        public styles()
        {
            InitializeComponent();
        }
    }
}

添加此文件最简单的方法是添加一个带有xaml的ContentView,然后将xaml和cs更改为从ResourceDictionary继承。
从此处,将文件添加到应用程序或页面的合并词典中:

<Application xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:foo="clr-namespace:DELETEME"
         x:Class="DELETEME.App">

    <Application.Resources>
       <ResourceDictionary>
           <ResourceDictionary.MergedDictionaries>
               <foo:styles />
           </ResourceDictionary.MergedDictionaries>
       </ResourceDictionary>
    </Application.Resources>
</Application>

这应该可以解决您的错误。示例如下。
Bar.cs类别:

public class Bar : ContentView
{
    public static readonly BindableProperty ColorsProperty =
        BindableProperty.Create(nameof(Colors), typeof(Colors), typeof(Bar));

    public Colors Colors
    {
        get => (Colors)GetValue(ColorsProperty);
        set => SetValue(ColorsProperty, value);
    }

    public Bar()
    {
        var b1 = new BoxView { BackgroundColor = Colors.Negative };
        var b2 = new BoxView { BackgroundColor = Colors.Neutral };
        var b3 = new BoxView { BackgroundColor = Colors.Positive };

        var sl = new StackLayout();

        sl.Children.Add(b1);
        sl.Children.Add(b2);
        sl.Children.Add(b3);

        Content = sl;
    }
}

xaml类:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:foo="clr-namespace:DELETEME"
         x:Class="DELETEME.MainPage">

    <StackLayout>
        <foo:Bar />
    </StackLayout>

</ContentPage>

运行结果:

相关问题