我制作了一个名为 ImageButton 的自定义控件,它允许我为 Up、Down 和 Inactive 状态设置不同的图像。它还可以在“正常”模式或“锁定”模式下运行。
除了一小部分之外,它工作正常……我在 XAML 中设置的值不会立即应用。它只使用默认值。
这是 ImageButton.cs
public class ImageButton : Image
{
public enum State
{
Inactive,
Up,
Down
};
public static readonly BindableProperty CommandProperty =
BindableProperty.Create("Command", typeof(ICommand), typeof(ImageButton), null);
public static readonly BindableProperty SourceUpProperty =
BindableProperty.Create("SourceUp", typeof(string), typeof(ImageButton), null);
public static readonly BindableProperty SourceDownProperty =
BindableProperty.Create("SourceDown", typeof(string), typeof(ImageButton), null);
public static readonly BindableProperty SourceInactiveProperty =
BindableProperty.Create("SourceInactive", typeof(string), typeof(ImageButton), null);
public static readonly BindableProperty ToggleProperty =
BindableProperty.Create("Toggle", typeof(bool), typeof(ImageButton), false);
public static readonly BindableProperty ToggleStateProperty =
BindableProperty.Create("ToggleState", typeof(State), typeof(ImageButton), State.Up, BindingMode.TwoWay);
public ImageButton()
{
Initialize();
}
public void Initialize()
{
switch (ToggleState) // <- this is returning "State.Up" (the default) no matter what is set in the xaml.
{
case State.Up:
Source = SourceUp;
break;
case State.Down:
Source = SourceDown;
break;
case State.Inactive:
Source = SourceInactive;
break;
default:
Source = SourceUp;
break;
}
GestureRecognizers.Add(new TapGestureRecognizer
{
Command = TransitionCommand
});
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
private ICommand TransitionCommand
{
get
{
return new Command(async () =>
{
if (ToggleState != State.Inactive)
{
AnchorX = 0.48;
AnchorY = 0.48;
await this.ScaleTo(0.8, 50, Easing.Linear);
if (Toggle)
{
if (ToggleState == State.Down)
ToggleState = State.Up;
else
ToggleState = State.Down;
}
await this.ScaleTo(1, 50, Easing.Linear);
if (Command != null)
{
Command.Execute(null);
}
}
});
}
}
public string SourceUp
{
get { return (string)GetValue(SourceUpProperty); }
set { SetValue(SourceUpProperty, value); }
}
public string SourceDown
{
get { return (string)GetValue(SourceDownProperty); }
set { SetValue(SourceDownProperty, value); }
}
public string SourceInactive
{
get { return (string)GetValue(SourceInactiveProperty); }
set { SetValue(SourceInactiveProperty, value); }
}
public bool Toggle
{
get { return (bool)GetValue(ToggleProperty); }
set { SetValue(ToggleProperty, value); }
}
public State ToggleState
{
get { return (State)GetValue(ToggleStateProperty); }
set
{
SetValue(ToggleStateProperty, value);
switch (value)
{
case State.Up:
Source = SourceUp;
break;
case State.Down:
Source = SourceDown;
break;
case State.Inactive:
Source = SourceInactive;
break;
default:
Source = SourceUp;
break;
}
}
}
}
如果我使用“源”进行设置,则该按钮有效,如下所示:
<custom:ImageButton
Source="i_left.png"
SourceUp="i_left.png"
SourceDown="i_right.png"
SourceInactive="i_close.png"
Toggle="True"
ToggleState="Up"
WidthRequest="{StaticResource IconMedium}"
HeightRequest="{StaticResource IconMedium}"
Command="{Binding ImageButton1Command}"/>
我不需要指定“Source”,因为在构造函数中我根据初始状态设置了它。
但似乎“ToggleState”尚未设置为我的 xaml 值。
我正在尝试像这样设置它
<custom:ImageButton
SourceUp="i_left.png"
SourceDown="i_right.png"
SourceInactive="i_close.png"
Toggle="True"
ToggleState="Down"
WidthRequest="{StaticResource IconMedium}"
HeightRequest="{StaticResource IconMedium}"
Command="{Binding ImageButton1Command}"/>
加载时它应该在“i_right.png”图像上,但它不是。
按答案编辑:以下课程按预期工作!
public class ImageButton : Image
{
public enum State
{
Inactive,
Up,
Down
};
public static readonly BindableProperty CommandProperty =
BindableProperty.Create("Command", typeof(ICommand), typeof(ImageButton), null, propertyChanged: OnStateChanged);
public static readonly BindableProperty SourceUpProperty =
BindableProperty.Create("SourceUp", typeof(ImageSource), typeof(ImageButton), null, propertyChanged: OnStateChanged);
public static readonly BindableProperty SourceDownProperty =
BindableProperty.Create("SourceDown", typeof(ImageSource), typeof(ImageButton), null, propertyChanged: OnStateChanged);
public static readonly BindableProperty SourceInactiveProperty =
BindableProperty.Create("SourceInactive", typeof(ImageSource), typeof(ImageButton), null, propertyChanged: OnStateChanged);
public static readonly BindableProperty ToggleProperty =
BindableProperty.Create("Toggle", typeof(bool), typeof(ImageButton), false);
public static readonly BindableProperty ToggleStateProperty =
BindableProperty.Create("ToggleState", typeof(State), typeof(ImageButton), State.Up, BindingMode.TwoWay, propertyChanged: OnStateChanged);
public ImageButton()
{
Initialize();
}
public void Initialize()
{
GestureRecognizers.Add(new TapGestureRecognizer
{
Command = TransitionCommand
});
}
static void OnStateChanged(BindableObject bindable, object oldValue, object newValue)
{
var imageButton = bindable as ImageButton;
imageButton.SetState();
}
public void SetState()
{
switch (ToggleState)
{
case State.Up:
Source = SourceUp;
break;
case State.Down:
Source = SourceDown;
break;
case State.Inactive:
Source = SourceInactive;
break;
default:
Source = SourceUp;
break;
}
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
private ICommand TransitionCommand
{
get
{
return new Command(async () =>
{
if (ToggleState != State.Inactive)
{
AnchorX = 0.48;
AnchorY = 0.48;
await this.ScaleTo(0.8, 50, Easing.Linear);
if (Toggle)
{
if (ToggleState == State.Down)
ToggleState = State.Up;
else
ToggleState = State.Down;
}
await this.ScaleTo(1, 50, Easing.Linear);
if (Command != null)
{
Command.Execute(null);
}
}
});
}
}
public ImageSource SourceUp
{
get { return (ImageSource)GetValue(SourceUpProperty); }
set { SetValue(SourceUpProperty, value); }
}
public ImageSource SourceDown
{
get { return (ImageSource)GetValue(SourceDownProperty); }
set { SetValue(SourceDownProperty, value); }
}
public ImageSource SourceInactive
{
get { return (ImageSource)GetValue(SourceInactiveProperty); }
set { SetValue(SourceInactiveProperty, value); }
}
public bool Toggle
{
get { return (bool)GetValue(ToggleProperty); }
set { SetValue(ToggleProperty, value); }
}
public State ToggleState
{
get { return (State)GetValue(ToggleStateProperty); }
set { SetValue(ToggleStateProperty, value); }
}
}
在调用构造函数时 - 尚未设置来自 XAML 的可绑定属性。因此,您将获得默认值。要检测属性的更新并正确设置控件的状态 - 您可以使用属性更改的回调方法。
我的建议是对每个可绑定属性使用属性更改回调,其值可能会影响控件的当前状态(因为您永远无法确定加载期间从 XAML 设置属性值的顺序/顺序)。
例如:
public static readonly BindableProperty ToggleStateProperty =
BindableProperty.Create("ToggleState", typeof(State), typeof(ImageButton), State.Up, BindingMode.TwoWay, propertyChanged: OnToggleStateChanged);
static void OnToggleStateChanged (BindableObject bindable, object oldValue, object newValue)
{
// Property changed implementation goes here
Initialize();
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句