【问题标题】:Xamarin.Forms and Triggers: hire an action during a limited timeXamarin.Forms 和触发器:在有限的时间内雇用一个动作
【发布时间】:2021-05-14 09:00:09
【问题描述】:

我开发了一个可以播放音频流源的 Xamarin.Forms 应用

为此,我在屏幕底部显示了一个小“栏”。该栏包含:

  • 一个“播放”/“停止” Button
  • Label,名称为当前标题
  • “关闭”Button

我想在 短时间内显示错误消息而不是当前标题,当错误发生时(例如无法访问互联网或 URL 无法访问) ),在两种Labels 之间有一个小动画/过渡

为此,我在 ViewModel 中有一个 HasError 属性:

bool hasError = false;
public bool HasError
{
    get { return hasError; }
    set { SetProperty(ref hasError, value); }
}

我想通过Triggers 管理这个。

我可以这样做:

<Label x:Name="RadioName"
        Text="{Binding CurrentTitle}" 
        Style="{StaticResource RadioLabelStyle}"
        Grid.Column="1">
    <Label.Triggers>
            <DataTrigger Binding="{Binding HasError}" Value="false" TargetType="Label">
                <Setter Property="IsVisible" Value="True" />
            </DataTrigger>
            <DataTrigger Binding="{Binding HasError}" Value="true" TargetType="Label">
                <Setter Property="IsVisible" Value="False" />
            </DataTrigger>
    </Label.Triggers>
</Label>
<Label x:Name="RadioError"
        Text="{x:Static strings:Strings.RadioErrorAccessMessage}"
        Style="{StaticResource ErrorRadioLabelStyle}"
        Grid.Column="1">
    <Label.Triggers>
            <DataTrigger Binding="{Binding HasError}" Value="false" TargetType="Label">
                <Setter Property="IsVisible" Value="False" />
            </DataTrigger>
            <DataTrigger Binding="{Binding HasError}" Value="true" TargetType="Label">
                <Setter Property="IsVisible" Value="True" />
            </DataTrigger>
    </Label.Triggers>
</Label>

这很好用,但在这种情况下,我没有任何时间限制或任何过渡/动画。

是否可以添加时间限制和过渡/动画?

【问题讨论】:

  • 这个案例有什么更新吗?
  • @WendyZang-MSFT 我相信我的解决方案回答了原始问题等等,但不幸的是,OP 不断更改问题的条款/条件,我稍后会尝试看看,您能否确认它是否有效?
  • 给定的解决方案适用于ConnectionStatus 问题。但是,管理在 VM 中管理的其他错误(如 URL 不可达)似乎不是更好的方法,因为这需要在 View 的代码隐藏中引用 VM 的某些属性......所以我终于使用了VM 中的 ShowError 属性触发错误的显示,而不使用 Triggers 更长的时间。

标签: c# xaml xamarin.forms triggers datatrigger


【解决方案1】:
  1. xaml 部分使用MultiTrigger,这里以Label 为例
    <Label TextColor="Black" Text="Online" FontSize="25">
        <Label.Triggers>
            <MultiTrigger TargetType="{x:Type Label}">
                <MultiTrigger.Conditions>
                    <BindingCondition Binding="{Binding ConnectionStatus}" Value="false"/>
                </MultiTrigger.Conditions>
                <Setter Property="BackgroundColor" Value="Orange"/>
                <Setter Property="Text" Value="Error Connection Lost"/>
            </MultiTrigger>
         </Label.Triggers>
    </Label>
  • 定义ConnectionStatus属性
private bool _ConnectionStatus = true;

        public bool ConnectionStatus
        {
            get => _ConnectionStatus;
            set => SetProperty(ref _ConnectionStatus, value); //raise InotifyPropertyChanged
        }

注意:我没有包含 Inotifyproperty 事件代码(这里有很多关于它的答案)

  1. 逻辑部分:对于丢失的连接,您可以使用 Xamarin Essentials 中的 ConnectivityChanged 事件:
  • 订阅活动
protected override void OnAppearing()
{
    base.OnAppearing();
    Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;
}
  • 取消订阅活动
protected override void OnDisappearing()
{
    base.OnDisappearing();
    Connectivity.ConnectivityChanged -= Connectivity_ConnectivityChanged;
}
  • 处理事件:连接丢失后将显示错误消息 5 秒。
async void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
{
    var access = e.NetworkAccess;
    if (access != NetworkAccess.Internet)
    {
        VM.ConnectionStatus = false;
        await Task.Delay(TimeSpan.FromSeconds(5));
        VM.ConnectionStatus = true;
    }
}

注意

VM 是对您的视图模型的引用,应该在其中定义ConnectionStatus,也不要忘记正确设置您的页面BindingContext

如果您不想使用视图模型,只需在代码中而不是视图模型中定义ConnectionStatus 属性(并处理INotifyPropertyChanged)即可。在那种情况下ConnectionStatus = false; 和`BindingContext = this;。

【讨论】:

  • 我认为这并不能真正解决他的问题。他在问如何对通过触发器显示的 UI 元素设置时间限制
  • @Jason 感谢您指出,我已经更新了我的答案
  • 嗨@Cfun 感谢您的建议。所以你认为我需要从视图中调用 ViewModel(就像你对 VM.ConnectionStatus = false 所做的那样)来实现这一点?我想避免这种情况,但我可能别无选择。
  • 您完全可以避免它,只需在您的代码中而不是 vm 中定义 ConnectionStatus 属性(并处理 INotifyPropertyChanged)。那案子ConnectionStatus = false;别忘了在InitializeComponent后面设置BindingContext = this;
  • 是的,但是在这种情况下,我在代码隐藏中有逻辑部分......是否可以使用 ViewModel 的属性而不是 Connectivity.ConnectivityChanged 事件?我为错误创建了一个“通用”属性(没有互联网访问或其他问题):所以我想将触发器绑定到这个属性。我需要为此在 ViewModel 中创建一个事件吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-05
  • 2016-03-23
  • 2017-07-28
  • 2021-10-09
  • 2018-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多