任务内未触发更改的属性

问题描述 投票:0回答:1

我有一个简单的应用程序,在某些任务运行时显示进度环,并在任务完成后立即隐藏进度环。这段代码的问题是进度条永远不会折叠。

我在值转换器类中保留了一个断点,即使在值更改后它也不会收到 false 值。因此,ProgressRing 永远不会塌陷。我该如何解决这个问题?

这是我的视图模型:

public class TestVM : INotifyPropertyChanged
    {
        private bool _isRingVisible;
        public bool IsRingVisible
        {
            get => _isRingVisible;
            set
            {
                _isRingVisible = value;
                OnPropertyChanged(nameof(IsRingVisible));
            }
        }
        public TestVM()
        {
            Task.Run(async () => await DoSomething());
        }

        private async Task DoSomething()
        {
            IsRingVisible = true;
            await Task.Delay(5000);
            IsRingVisible = false; //Value set to false but when I have a break point in the value converter class, it never receives this value.
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

在 xaml 中,我有一个简单的 UI,如下所示,

<Page.Resources>
        <converter:BoolToVisibilityConverter x:Key="boolToVisibility"/>
    </Page.Resources>
<Grid>
        <Border x:Name="BdrProgressRing" 
                    Grid.Row="0" 
                    Grid.RowSpan="2" 
                    Background="Red"
                    VerticalAlignment="Center"
                    Opacity="0.6" 
                    Visibility="{x:Bind vm.IsRingVisible,Mode=OneWay,Converter={StaticResource boolToVisibility}}">
        </Border>
        <ProgressRing x:Name="PgRing" 
                          Grid.Row="0" 
                          Grid.RowSpan="2"
                          Visibility="{Binding ElementName=BdrProgressRing, Path=Visibility}"
                          IsActive="True"  
                          VerticalAlignment="Center"
                          Width="90"
                          Height="90"/>
    </Grid>

这是我的xaml.cs

public sealed partial class MainPage : Page
    {
        public TestVM vm { get; set; }
        public MainPage()
        {
            this.InitializeComponent();
            vm = new TestVM();
            this.DataContext = this;
        }
    }
c# uwp async-await
1个回答
1
投票

改变

Task.Run(async () => await DoSomething()) ;

_ = DoSomething();

可能您只允许从主 UI 线程更改属性,而不是从池中

Task
。了解有关 WPF 中同步上下文的更多信息。


但是,以上是不好的做法。任何异步方法都应该等待。简单地将从

DoSomething()
返回的任务分配给局部变量是不够的。

由于您无法在构造函数中等待,因此视图模型应该有一个公共可等待方法,该方法实际上由调用者等待,例如

public TestVM()
{
}

public Task Initialize()
{
    return DoSomething();
}

然后在视图中的异步 Loaded 事件处理程序中调用

await vm.Initialize();

public MainPage()
{
    InitializeComponent();
    vm = new TestVM();
    DataContext = this;

    Loaded += async (s, e) => await vm.Initialize();
}
© www.soinside.com 2019 - 2024. All rights reserved.