【问题标题】:WPF Update UI from DataTable through BindingWPF 通过绑定从 DataTable 更新 UI
【发布时间】:2014-08-30 11:03:53
【问题描述】:

对于我正在做的一个 WPF 项目,我关注了 MSDN 的 tutorials 线程、调度程序等。 但我无法让 UI 更新。唯一不同的是,我正在更新一个 DataTable,并将该 DataTable 绑定到我的 XAML。

下面是代码:

Sub Approve_Click(obj As Object, e As RoutedEventArgs)
    btnApprove.Dispatcher.BeginInvoke(DispatcherPriority.Normal, New ApproveDelegate(AddressOf ApproveThread))
End Sub

Sub ApproveThread()
    Dim Invoice_Model As New COGENT_Model.Invoice_Model
    For Each row In dt.Rows
        If row("check") = True Then
            Try
                '//calling db functions here...
                row("status") = 1
            Catch ex As Exception
                row("message") = ex.Message
                row("status") = 2
            End Try
        End If
    Next
End Sub

这是我的 xaml:

<DataGrid x:Name="dgvApprove" BorderThickness="1,0,0,0" SelectionMode="Single" AutoGenerateColumns="False"
                      CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" RowDetailsVisibilityMode="Collapsed">
                <DataGrid.Columns>
                    <DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Image Name="IsReadImage" Source="../Images/Status/statusNone.png"/>
                                <DataTemplate.Triggers>
                                    <DataTrigger Binding="{Binding status,Mode=TwoWay}" Value="1">
                                        <Setter TargetName="IsReadImage" Property="Source" Value="../Images/Status/statusApproved.png"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding status,Mode=TwoWay}" Value="2">
                                        <Setter TargetName="IsReadImage" Property="Source" Value="../Images/Status/statusCanceled.png"/>
                                    </DataTrigger>
                                </DataTemplate.Triggers>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridCheckBoxColumn Binding="{Binding check}"/>
                    <DataGridTextColumn Binding="{Binding name_full}"/>
                    <DataGridTextColumn Binding="{Binding status}"/>
                    <DataGridTextColumn Binding="{Binding message}"/>
                </DataGrid.Columns>
            </DataGrid>

在窗口加载时,我正在应用 ItemSource 属性。这段代码通常可以正常工作,可以满足我的所有需求,但在全部完成之前不会更新 UI。

快速解释:如果批准,我基本上想要绿色图像,如果出现问题,我想要红色图像。

任何帮助将不胜感激!

【问题讨论】:

    标签: .net wpf multithreading xaml


    【解决方案1】:

    UI 是单线程的,您的所有代码都从 UI 线程运行 - 因此它会阻塞 UI 直到完成。要获得您想要的行为,您需要为“ApproveThread”生成一个后台线程,并将行值更新分派回 UI 线程。

    C# 示例:

    void Approve_Click(object obj, RoutedEventArgs e)
    {
        Task.Factory.StartNew(new Action(ApproveThread));
    }
    
    void ApproveThread() 
    {
        var Invoice_Model = new COGENT_Model.Invoice_Model();
        foreach (var row in dt.Rows)
        {
            if (row["check"])
            {
                try
                {
                    '//calling db functions here...
                    Dispatcher.BeginInvoke(new Action(() => 
                        row["status"] = 1
                    ));
                }
                catch (Exception ex)
                {
                    Dispatcher.BeginInvoke(new Action(() => {
                        row["message"] = ex.Message;
                        row["status"] = 2;
                    }));
                }
            }
        }
    }
    

    【讨论】:

    • @user3524375 啊抱歉,我会的,但我在 VB 方面不够专业,无法完成。如果您有兴趣,我可以添加一个 C# 示例?
    • 绝对!您能提供的任何帮助将不胜感激!
    • @user3524375 在上面编辑。我使用Task.Factory.StartNew 作为线程,但您可以使用BackgroundWorker 或只是Thread 或其他。
    【解决方案2】:

    我给了 McGarnagle 正确的答案,因为他是正确的。但是对于所有那些 VB 编码器,普通转换器无法正确转换代码:

    例如,在我得到的调度程序中:

    Dispatcher.BeginInvoke(New Action()(InlineAssignHelper(row("status"), 1)))
    

    但是 InlineAssignHelper 不起作用。 因此,经过更多搜索(如果您使用的是 .Net 4+),您可以简单地执行以下操作:

    /to call the thread
    Task.Factory.StartNew(Sub() DoBackgroundWork())
    
    /to update the UI.
    Dispatcher.BeginInvoke(Sub() txtBox1.Text = "End")
    

    找到VB解决方案here...

    【讨论】:

      猜你喜欢
      • 2011-04-07
      • 1970-01-01
      • 2011-03-31
      • 2016-12-17
      • 1970-01-01
      • 2020-10-27
      • 2013-06-20
      • 2021-08-20
      • 2013-07-21
      相关资源
      最近更新 更多