自定义控件的属性只能由 StaticResource 填充,不能用 XAML 中定义的值填充
Properties of custom control can only be filled by StaticResource but not with values defined in XAML
我基于此 https://www.clearpeople.com/insights/blog/2019/February/how-to-create-a-contentview-with-expandable-functionality 创建了自己的 ExpandableView
但作为所有 C# 代码。
我的控件看起来像这样(没有动画部分)
public class ExpandableView : ContentView
{
public static readonly BindableProperty ExpandableContentProperty = BindableProperty.Create(nameof(ExpandableContent), typeof(View), typeof(ExpandableView));
public static readonly BindableProperty TitleTextProperty = BindableProperty.Create(nameof(TitleText), typeof(string), typeof(ExpandableView));
public View ExpandableContent
{
get => this._content;
set
{
if (this._content == value)
{
return;
}
OnPropertyChanging();
if (this._content != null)
{
this._ContentLayout.Children.Remove(this._content);
}
this._content = value;
this._ContentLayout.Children.Add(this._content);
OnPropertyChanged();
}
}
public string TitleText
{
get => this._Title.Text;
set
{
if (this._Title.Text == value)
{
return;
}
OnPropertyChanging();
this._Title.Text = value;
OnPropertyChanged();
}
}
private readonly StackLayout _OuterLayout;
private readonly StackLayout _ContentLayout;
private readonly StackLayout _TitleLayout;
private View _content;
private readonly Label _Title;
public ExpandableView()
{
this._OuterLayout = new StackLayout();
this._ContentLayout = new StackLayout();
this._TitleLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
};
this._Title = new Label
{
HorizontalOptions = new LayoutOptions(LayoutAlignment.Start, true),
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
Text = "Title",
};
this._Title.FontSize = Device.GetNamedSize(NamedSize.Medium, this._Title);
this._TitleLayout.Children.Add(this._Title);
this._OuterLayout.Children.Add(this._TitleLayout);
this._OuterLayout.Children.Add(this._ContentLayout);
Content = this._OuterLayout;
}
}
但是现在,当我尝试像往常一样在 XAML 中使用它时:
<controls:ExpandableView TitleText="Equipment">
<controls:ExpandableView.ExpandableContent>
<StackLayout>
<Label Text="EQ_12345" />
<Button Command="{Binding ShowDatacommand}" />
</StackLayout>
</controls:ExpandableView.ExpandableContent>
</controls:ExpandableView>
将属性设置为某些值会导致标题仍向我显示 "Title",但不会显示任何内容。如果我改为将所有内容放入 StaticResource
一切正常:
<controls:ExpandableView ExpandableContent="{StaticResource ExpendableViewContent}"
TitleText="{StaticResource EquiString}" />
在测试时,我在属性中设置了一些断点,并且只有在我使用 {StaticResource}
时才设置了属性。 XAML 中直接定义的所有值从未传递给属性。我在这里做错了什么?
定义您自己的 BindableProperty 属性时,应通过 BindableObject.SetValue/BindableObject.GetValue 访问值的最终来源。 Xamarin 运行时可以直接使用它,而不是通过您的 get/set 方法。
以 TitleText 为例,实现应该是这样的:
public string TitleText
{
get => (string)GetValue(TitleTextProperty);
set
{
SetValue(TitleTextProperty, value);
}
}
linked 文章确实做到了这一点。
为了在 属性 和显示的标题之间创建 link,在构造函数中建立数据绑定 link 标题标签的文本到 TitleText 属性 在 ExpandableView 构造函数中:
_Title.SetBinding(Label.TextProperty, new Binding(nameof(TitleText)) { Source = this });
我基于此 https://www.clearpeople.com/insights/blog/2019/February/how-to-create-a-contentview-with-expandable-functionality 创建了自己的 ExpandableView
但作为所有 C# 代码。
我的控件看起来像这样(没有动画部分)
public class ExpandableView : ContentView
{
public static readonly BindableProperty ExpandableContentProperty = BindableProperty.Create(nameof(ExpandableContent), typeof(View), typeof(ExpandableView));
public static readonly BindableProperty TitleTextProperty = BindableProperty.Create(nameof(TitleText), typeof(string), typeof(ExpandableView));
public View ExpandableContent
{
get => this._content;
set
{
if (this._content == value)
{
return;
}
OnPropertyChanging();
if (this._content != null)
{
this._ContentLayout.Children.Remove(this._content);
}
this._content = value;
this._ContentLayout.Children.Add(this._content);
OnPropertyChanged();
}
}
public string TitleText
{
get => this._Title.Text;
set
{
if (this._Title.Text == value)
{
return;
}
OnPropertyChanging();
this._Title.Text = value;
OnPropertyChanged();
}
}
private readonly StackLayout _OuterLayout;
private readonly StackLayout _ContentLayout;
private readonly StackLayout _TitleLayout;
private View _content;
private readonly Label _Title;
public ExpandableView()
{
this._OuterLayout = new StackLayout();
this._ContentLayout = new StackLayout();
this._TitleLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
};
this._Title = new Label
{
HorizontalOptions = new LayoutOptions(LayoutAlignment.Start, true),
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
Text = "Title",
};
this._Title.FontSize = Device.GetNamedSize(NamedSize.Medium, this._Title);
this._TitleLayout.Children.Add(this._Title);
this._OuterLayout.Children.Add(this._TitleLayout);
this._OuterLayout.Children.Add(this._ContentLayout);
Content = this._OuterLayout;
}
}
但是现在,当我尝试像往常一样在 XAML 中使用它时:
<controls:ExpandableView TitleText="Equipment">
<controls:ExpandableView.ExpandableContent>
<StackLayout>
<Label Text="EQ_12345" />
<Button Command="{Binding ShowDatacommand}" />
</StackLayout>
</controls:ExpandableView.ExpandableContent>
</controls:ExpandableView>
将属性设置为某些值会导致标题仍向我显示 "Title",但不会显示任何内容。如果我改为将所有内容放入 StaticResource
一切正常:
<controls:ExpandableView ExpandableContent="{StaticResource ExpendableViewContent}"
TitleText="{StaticResource EquiString}" />
在测试时,我在属性中设置了一些断点,并且只有在我使用 {StaticResource}
时才设置了属性。 XAML 中直接定义的所有值从未传递给属性。我在这里做错了什么?
定义您自己的 BindableProperty 属性时,应通过 BindableObject.SetValue/BindableObject.GetValue 访问值的最终来源。 Xamarin 运行时可以直接使用它,而不是通过您的 get/set 方法。
以 TitleText 为例,实现应该是这样的:
public string TitleText
{
get => (string)GetValue(TitleTextProperty);
set
{
SetValue(TitleTextProperty, value);
}
}
linked 文章确实做到了这一点。
为了在 属性 和显示的标题之间创建 link,在构造函数中建立数据绑定 link 标题标签的文本到 TitleText 属性 在 ExpandableView 构造函数中:
_Title.SetBinding(Label.TextProperty, new Binding(nameof(TitleText)) { Source = this });