【问题标题】:Reporting progress from ViewModel method executed in a Task报告任务中执行的 ViewModel 方法的进度
【发布时间】:2017-08-25 07:42:58
【问题描述】:

我正在尝试报告在任务中执行的 ViewModel (MVVM Light) 方法的进度。 ProgressViewModel 包含一个 ProgressModel 属性,该属性提供描述当前状态的属性。这些属性绑定到 Xceed BusyIndicator。到现在为止还挺好。但它没有按预期工作。 ProgressModel.IsRunning 绑定到 BusyIndiciator.IsBusy 并切换可见性 - 有效。 ProgressModel.DescriptionProgressModel.Percentage 绑定到 TextBlock.Text/ProgressBar.Value - 但它们没有更新...

所以...既然IsRunning 有效,那么DescriptionProgress...有什么问题?

// Model
public sealed class ProgressModel: ObservableObject
{
    private string m_description;
    private float m_percentage;
    private bool m_running;

    public string Description
    {
        get { return m_description; }
        set { Set(ref m_description, value); }
    }
    public float Percentage
    {
        get { return m_percentage; }
        set { Set(ref m_percentage, value); }
    }
    public bool IsRunning
    {
        get { return m_running; }
        set{Set(ref m_running, value);}
    }

    public void Initiate()
    {
        Description = string.Empty;
        Percentage = 0;
        IsRunning = true;
    }
}
// Command
private void DownloadWatch()
{
    DispatcherHelper.UIDispatcher.Invoke(() =>
    {
        Progress.Initiate();
    });
    using (var watch = new PolarWatch())
    {
        watch.Connect();
        for (var i = 0; i < watch.Sessions.Count; i++)
        {
            DispatcherHelper.UIDispatcher.Invoke(() =>
            {
                Progress.Description = $"Writing session data for '{session.DateTime}'...";
            });
        }
    }
    DispatcherHelper.UIDispatcher.Invoke(() =>
    {
        Progress.IsRunning = false;
    });
}
// View
<xctk:BusyIndicator Name="Busy" IsBusy="{Binding Progress.IsRunning}">
    <xctk:BusyIndicator.BusyContentTemplate>
        <DataTemplate>
            <Grid Width="150">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Progress.Description}"/>
                <ProgressBar Grid.Row="1" Grid.Column="0" Value="{Binding Progress.Percentage}" Height="14" Margin="0,5,0,0"/>
            </Grid>
        </DataTemplate>
    </xctk:BusyIndicator.BusyContentTemplate>
    <xctk:BusyIndicator.ProgressBarStyle>
        <Style TargetType="ProgressBar">
            <Setter Property="Visibility" Value="Collapsed"/>
        </Style>
    </xctk:BusyIndicator.ProgressBarStyle>

【问题讨论】:

  • 这通常可以通过将 IProgress 传递给您的任务来完成,请参阅msdn.microsoft.com/en-us/library/hh138298(v=vs.110).aspx
  • @MikeT:在 WPF 中,通常如上所示,只需设置绑定到 WPF 控件的进度值即可。 WPF 在这种情况下隐式处理跨线程更新,不需要Progress&lt;T&gt;。事实上,上面的代码有 Invoke() 调用,甚至没有必要;即使没有这些绑定也可以工作。
  • 你试过set { Set( nameof(Percentage),ref m_percentage, value); }吗?
  • 啊,等一下……你确定它们是没有设置的吗?只是时间问题吗?在您执行 watch.Connect 的功能中,然后您在禁用 BusyIndi​​cator 之后迭代会话。莫非执行得这么快,你都看不到?
  • 也许在您观看之前尝试添加Progress.Description="Connecting ..."。连接并查看它是否显示在指标中。

标签: c# wpf mvvm progress


【解决方案1】:

ItemTemplate 中根元素的DataContext 与控件本身的DataContext 不同。试试这个:

<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding DataContext.Progress.Description, RelativeSource={RelativeSource AncestorType=xctk:BusyIndicator}}"/>
<ProgressBar Grid.Row="1" Grid.Column="0" Value="{Binding DataContext.Progress.Percentage,RelativeSource={RelativeSource AncestorType=xctk:BusyIndicator}}" Height="14" Margin="0,5,0,0"/>

或者设置GridDataContext

<Grid Width="150" DataContext="{Binding DataContext.Progress, RelativeSource={RelativeSource AncestorType=xctk:BusyIndicator}}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Description}"/>
    <ProgressBar Grid.Row="1" Grid.Column="0" Value="{Binding Percentage}" Height="14" Margin="0,5,0,0"/>
</Grid>

【讨论】:

  • 听起来不错。我会在星期一试试这个。你能给我一个简短的解释为什么DataContext不一样吗?我希望如果我没有指定另一个 DataContext 根/父 DataContext 将被使用...
  • 不,ContentControl的ContentTemplate的DataContext就是ContentControl的内容。
  • 那是一些不错的措辞。必须读两遍,直到我明白为止。谢谢 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
相关资源
最近更新 更多