任务内部未触发属性更改

时间:2020-07-01 21:38:54

标签: c# uwp async-await

我有一个简单的应用程序,其中在运行某些任务时显示进度环,并在完成时立即隐藏进度环。这段代码的问题是进度栏永远不会折叠。我在值转换器类中保留一个断点,即使在值更改后也永远不会收到false值。结果,ProgressRing永不崩溃。请帮忙。

这是我的ViewModel

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;
        }
    }

1 个答案:

答案 0 :(得分:1)

更改

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

收件人

_ = DoSomething();

可能您只允许从主UI线程更改属性,而不允许从池Task更改属性。了解有关WPF中的同步上下文的更多信息。


但是,以上是不好的做法。任何异步方法都应等待。仅将从DoSomething()返回的任务分配给局部变量是不够的。

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

public TestVM()
{
}

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

然后在视图的异步加载事件处理程序中调用await vm.Initialize();

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

    Loaded += async (s, e) => await vm.Initialize();
}
相关问题