我想控制視圖模型中的 ToggleButton 狀態,以便能夠與它進行通信,它是否可以切換。
這是 ToggleButton 的 xaml:
<controls:ToggleButton Command="{Binding StartStopCommand}" WidthRequest="120" Margin="10,10,10,10">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ToggleStates">
<VisualState Name="ToggledOff">
<VisualState.Setters>
<Setter Property="Text" Value="START" />
<Setter Property="FontSize" Value="14" />
<Setter Property="BackgroundColor" Value="#474747" />
<Setter Property="TextColor" Value="White" />
</VisualState.Setters>
</VisualState>
<VisualState Name="ToggledOn">
<VisualState.Setters>
<Setter Property="Text" Value="STOP" />
<Setter Property="FontSize" Value="14" />
<Setter Property="BackgroundColor" Value="#6e1413" />
<Setter Property="TextColor" Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</controls:ToggleButton>
ToggleButton 的 C# 部分:
public class ToggleButton : Button
{
public event EventHandler<ToggledEventArgs> Toggled;
public static BindableProperty IsToggledProperty =
BindableProperty.Create(nameof(IsToggled), typeof(bool), typeof(ToggleButton), false, propertyChanged: OnIsToggledChanged);
public ToggleButton()
{
Clicked = (sender, args) => IsToggled ^= true;
}
public bool IsToggled
{
set { SetValue(IsToggledProperty, value); }
get { return (bool)GetValue(IsToggledProperty); }
}
protected override void OnParentSet()
{
base.OnParentSet();
VisualStateManager.GoToState(this, "ToggledOff");
}
static async void OnIsToggledChanged(BindableObject bindable, object oldValue, object newValue)
{
ToggleButton toggleButton = (ToggleButton)bindable;
bool isToggled = (bool)newValue;
// Fire event
toggleButton.Toggled?.Invoke(toggleButton, new ToggledEventArgs(isToggled));
// Set the visual state
VisualStateManager.GoToState(toggleButton, isToggled ? "ToggledOn" : "ToggledOff");
}
}
如果某些邏輯結果不正確,我想在這里“取消”從 ViewModel 切換:
private async Task ActivateStartStopAsync()
{
if (this.StartStopON == false)
{
// Do something
this.StartStopON = true;
}
else
{
bool result = await App.Current.MainPage.DisplayAlert("About to be shut down", "Are you sure you want to turn it off?", "OK", "Cancel");
if (result)
{
// Do something
this.StartStopON = false;
}
}
}
public ICommand StartStopCommand { get; }
public MyViewModel()
{
this.StartStopCommand = new Command(async () => await ActivateStartStopAsync());
}
基本上我需要從 ViewModel 更改按鈕狀態。如何做到這一點?它應該在單擊事件之前以某種方式發生,還是我應該為此使用開關或復選框之類的東西?如果是這樣,那么我如何自定義復選框或切換看起來像一個按鈕?有什么例子嗎?
我試圖實作的邏輯:
- 按鈕是灰色的,帶有文本 START
- 單擊按鈕,顏色變為紅色并帶有文本 STOP
- 用戶單擊按鈕,彈出視窗出現選項 OK 和 CANCEL
- 如果用戶單擊 OK -> 按鈕變回灰色并帶有文本 START,彈出視窗消失
- If user clicks CANCEL -> button stays in same state = red colored with text STOP, popup window disappears. Same logic is repeated until user click OK in popup window.
uj5u.com熱心網友回復:
這是我想出的...
視窗.xaml:
為切換按鈕和彈出視窗分配資料背景關系,一切都在視圖模型類(Button_Toggle.cs)中處理
Window.xaml.cs:
再次,不多。
創建視圖模型的實體 (Button_Toggle.cs) 并分配資料背景關系
Button_Toggle.cs:
奇跡發生的地方。
在這里,您繼承了 Button 類,因此您可以完全控制并提供 Button 的資料背景關系。
為彈出視窗創建一個公共物件,它為彈出視窗提供資料背景關系。
給出任何輸入時,都會更新 buttonState 物件,然后進行更改以反映 buttonState 的當前狀態。
我不認為你真的需要走這么遠,可以在每個輸入中設定所有內容。
但是對我來說,布局有助于將來的擴展和除錯。
希望這有幫助并且有意義,如果沒有,請告訴我。
視窗.xaml:
<Window x:Class="Toggle_Change.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Toggle_Change"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Background="Red">
<Window.DataContext>
<local:Button_Toggle/>
</Window.DataContext>
<Grid>
<local:Button_Toggle x:Name="my_toggle_button" Background="#FF727272"/>
<Popup Name="my_popup">
</Popup>
</Grid>
Window.xaml.cs:
using System.Windows;
namespace Toggle_Change
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public Button_Toggle buttonToggle;
public MainWindow()
{
InitializeComponent();
buttonToggle = new Button_Toggle();
this.my_toggle_button.DataContext = buttonToggle;
this.my_popup.DataContext = buttonToggle.MyPopUp;
}
}
}
Button_Toggle.cs:
using System.Diagnostics;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace Toggle_Change
{
public class Button_Toggle :System.Windows.Controls.Button
{
public Popup MyPopUp;
#region private class
private enum StateType { NA,START,STOP,OK,CANCEL}
private class colors
{
public static readonly Brush Grey = new SolidColorBrush(color: System.Windows.Media.Color.FromArgb(0xFF,0x72,0x72,0x72));
public static readonly Brush Black = new SolidColorBrush(color: System.Windows.Media.Color.FromArgb(0xFF,0x00,0x00,0x00));
public static readonly Brush Red = new SolidColorBrush(color: System.Windows.Media.Color.FromArgb(0xFF,0xFF,0x00,0x00));
}
#endregion
#region private objects
private StateType buttonState = StateType.START;
#endregion
/// <summary>
/// update text based on the button state
/// </summary>
private void set_text()
{
switch (buttonState)
{
case StateType.START:
this.Content = "START";
this.Background = colors.Grey;
this.Foreground = colors.Black;
break;
case StateType.STOP:
this.Content = "STOP";
this.Background = colors.Grey;
this.Foreground = colors.Red;
break;
case StateType.OK:
break;
case StateType.CANCEL:
break;
default:
break;
}
}
/// <summary>
/// something was clicked, alter the button state based on the current state
/// </summary>
private void on_click()
{
Debug.WriteLine("CLICK");
switch (buttonState)
{
case StateType.NA:
buttonState =
StateType.START;
break;
case StateType.START:
buttonState =
StateType.STOP;
break;
case StateType.STOP:
MyPopUp.IsEnabled = true;
MyPopUp.IsOpen = true;
MyPopUp.Visibility = System.Windows.Visibility.Visible;
break;
case StateType.OK:
buttonState =
StateType.START;
MyPopUp.IsEnabled = false;
MyPopUp.IsOpen = false;
MyPopUp.Visibility = System.Windows.Visibility.Hidden;
break;
case StateType.CANCEL:
buttonState =
StateType.STOP;
MyPopUp.IsEnabled = false;
MyPopUp.IsOpen = false;
MyPopUp.Visibility = System.Windows.Visibility.Hidden;
break;
default:
break;
}
set_text();
}
private void ini_popup()
{
StackPanel _stackPanel;
Button _btnA;
Button _btnB;
_btnA = new Button();
_btnA.Content = "OK";
_btnA.Click = _btnA_Click;
_btnB = new Button();
_btnB.Content = "NO";
_btnB.Click = _btnB_Click;
_stackPanel =
new StackPanel();
_stackPanel.Orientation = Orientation.Horizontal;
_stackPanel.Children.Add(
_btnA);
_stackPanel.Children.Add(
_btnB);
MyPopUp = new Popup();
MyPopUp.Child = _stackPanel;
MyPopUp.Placement = PlacementMode.Center;
MyPopUp.PlacementTarget = this;
MyPopUp.PopupAnimation = PopupAnimation.Slide;
MyPopUp.Visibility = System.Windows.Visibility.Hidden;
}
private void _btnB_Click(object sender, System.Windows.RoutedEventArgs e)
{
buttonState = StateType.CANCEL;
OnClick();
}
private void _btnA_Click(object sender, System.Windows.RoutedEventArgs e)
{
buttonState = StateType.OK;
OnClick();
}
private void MyPopUp_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
Debug.WriteLine("Popup Is Doing Something");
}
private void Button_Toggle_Click(object sender, System.Windows.RoutedEventArgs e)
{
on_click();
}
public Button_Toggle() {
ini_popup();
MyPopUp.IsVisibleChanged = MyPopUp_IsVisibleChanged;
this.Click = Button_Toggle_Click;
this.set_text();
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/449549.html
