Xamarin:Visual State Manager和自定义属性 [英] Xamarin: Visual State Manager and custom properties
问题描述
我正在尝试使用Visual State Manager在自定义控件上设置自定义属性,但到目前为止我还没有运气.我的自定义控件只是带有附加可绑定属性的标签.
I am trying to set a custom property on a custom control using the Visual State Manager but I'm not having any luck so far. My custom control is just a label with an additional bindable property on it.
public class SelectableLabel : Label
{
public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create("IsSelected", typeof(bool), typeof(SelectableLabel), false);
public bool IsSelected
{
get { return (bool)GetValue(IsSelectedProperty); }
set
{
Console.WriteLine($"MDO: {Text}.IsSelected_set={value}");
SetValue(IsSelectedProperty, value);
}
}
当控件进入Selected
可视状态时,我在CollectionView中使用此控件来切换IsSelected
属性.
I use this control inside a CollectionView to toggle the IsSelected
property when the control enters the Selected
visual state.
<CollectionView
x:Name="cv"
ItemsSource="{Binding Names}"
SelectionMode="Multiple"
SelectedItems="{Binding SelectedNames, Mode=TwoWay}"
VerticalOptions="Fill">
<CollectionView.ItemTemplate>
<DataTemplate>
<local:SelectableLabel
x:Name="lblName"
Text="{Binding First}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup
x:Name="CommonStates">
<VisualState
x:Name="Normal">
<VisualState.Setters>
<Setter
Property="IsSelected"
Value="False" />
</VisualState.Setters>
</VisualState>
<VisualState
x:Name="Selected">
<VisualState.Setters>
<Setter
Property="IsSelected"
Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</local:SelectableLabel>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
当我在iOS模拟器上运行此命令时,视觉状态更改为Selected
时,看不到设置器被触发.如果我将设置器中的属性更改为BackgroundColor
或Text
,则会看到预期的行为.该问题似乎特定于自定义属性.我查看了Setter.Property
的文档,它指出可以将Setter应用于IsSelected
所在的BindableProperty
.我是在做错什么还是VSM不支持此功能?
When I run this on an iOS simulator, I'm not seeing the setter being fired when the visual state changes to Selected
. If I change the property in the setter to BackgroundColor
or Text
, I'm seeing the expected behavior. The problem seems specific to the custom property. I looked at the documentation for the Setter.Property
and it states that the Setter can be applied to a BindableProperty
which IsSelected
is. Am I doing something wrong or does the VSM not support this functionality?
本示例的CollectionView
部分无关紧要.这段代码也会发生同样的问题.
The CollectionView
part of this example is irrelevant. The same issue happens with this code.
public class SelectableEntry : Entry
{
public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create("IsSelected", typeof(bool), typeof(SelectableEntry), false);
public bool IsSelected
{
get { return (bool)GetValue(IsSelectedProperty); }
set
{
Console.WriteLine($"MDO: {Text}.IsSelected_set={value}");
var color = value ? Color.LightBlue : Color.LightPink;
SetValue(IsSelectedProperty, value);
SetValue(BackgroundColorProperty, color);
}
}
}
这是对应的XAML.当第一个自定义Entry控件获得焦点而第二个未获得焦点时,背景颜色发生变化.我也没有在控制台中看到我的WriteLine
语句.
Here is the corresponding XAML. The background color changes when the first custom Entry control receives focus while the second does not. I also don't see my WriteLine
statement in the console.
<local:SelectableEntry Text="First">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup
x:Name="CommonStates">
<VisualState
x:Name="Normal">
<VisualState.Setters>
<Setter
Property="BackgroundColor"
Value="LightBlue" />
</VisualState.Setters>
</VisualState>
<VisualState
x:Name="Focused">
<VisualState.Setters>
<Setter
Property="BackgroundColor"
Value="LightPink" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</local:SelectableEntry>
<local:SelectableEntry Text="Second">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup
x:Name="CommonStates">
<VisualState
x:Name="Normal">
<VisualState.Setters>
<Setter
Property="IsSelected"
Value="False" />
</VisualState.Setters>
</VisualState>
<VisualState
x:Name="Focused">
<VisualState.Setters>
<Setter
Property="IsSelected"
Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</local:SelectableEntry>
推荐答案
我尝试使用可绑定属性,以检查是否在VisualStateManager
中调用了属性.令人遗憾的是,即使在propertyChanged
方法中也无法调用它.我认为也许可绑定属性在VisualStateManager
中不起作用.
I have tried with Bindable Property to check whether property be invoked in VisualStateManager
. That's regrettable, it can not be invoked even in propertyChanged
method . I think maybe bindable property can not work in VisualStateManager
.
自定义Entry
代码如下:
public class SelectableEntry : Entry
{
public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create("IsSelected", typeof(bool), typeof(SelectableEntry), false ,propertyChanged:changedMethod);
private static void changedMethod(BindableObject bindable, object oldValue, object newValue)
{
Console.WriteLine($"MDO: {oldValue}.IsSelected_set={newValue}");
}
public bool IsSelected
{
get { return (bool)GetValue(IsSelectedProperty); }
set
{
Console.WriteLine($"MDO: {Text}.IsSelected_set={value}");
var color = value ? Color.LightBlue : Color.LightPink;
SetValue(IsSelectedProperty, value);
SetValue(BackgroundColorProperty, color);
}
}
}
解决方案:
但是,有 已附加可以在Style.Setters
中使用的属性 .然后您也可以在VisualState.Setters
中尝试一下.它也可以使用.
However , there is a Attached Properties that can be used in Style.Setters
. Then you can also have a try with it in VisualState.Setters
.It also will work .
附加的属性类代码如下:
Attached property class Code as follow :
public class SelectableEntryStyle
{
public static readonly BindableProperty IsSelectedProperty = BindableProperty.CreateAttached("IsSelected", typeof(bool), typeof(SelectableEntryStyle), false,propertyChanged:onChangedMethod);
private static void onChangedMethod(BindableObject bindable, object oldValue, object newValue)
{
Console.WriteLine($"MDO:IsSelected_set={newValue}");
var color = (bool)newValue ? Color.LightBlue : Color.LightPink;
var entry = bindable as Entry;
entry.SetValue(Entry.BackgroundColorProperty, color);
}
public static bool GetIsSelected(BindableObject view)
{
return (bool)view.GetValue(IsSelectedProperty);
}
public static void SetIsSelected(BindableObject view, bool value)
{
view.SetValue(IsSelectedProperty, value);
}
}
Xaml 的代码如下:
<local:SelectableEntry FontSize="18" Placeholder="Bindable Property">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="IsSelected"
Value="False" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="IsSelected"
Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</local:SelectableEntry>
<Entry Placeholder="Attached Property">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="local:SelectableEntryStyle.IsSelected"
Value="False" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="local:SelectableEntryStyle.IsSelected"
Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
然后,当Entry
为Normal
或Focused
时,控制台可以打印日志.
Then console can print log when Entry
is Normal
or Focused
.
02-18 14:26:27.360 I/mono-stdout(26014):MDO:IsSelected_set = True
02-18 14:26:27.360 I/mono-stdout(26014): MDO:IsSelected_set=True
02-18 14:26:28.675 I/mono-stdout(26014):MDO:IsSelected_set = False
02-18 14:26:28.675 I/mono-stdout(26014): MDO:IsSelected_set=False
效果:
这篇关于Xamarin:Visual State Manager和自定义属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!