【问题标题】:Databinding Progress Bar Not Binding数据绑定进度条未绑定
【发布时间】:2018-07-11 17:11:56
【问题描述】:

我搜索了很多解决方案,但似乎无法弄清楚。 (只是说,这将是一个很长的帖子)

前言:这不是 MVVM

问题:我有一个进度条。我目前正在尝试从 xaml 的 .cs 文件中将公共双精度绑定到它。但是,每当我使用 value 的 bind 函数时,它永远不会起作用,导致 iNotifyPropertyChanged 不起作用,等等......

它绑定的变量用于更新进度条值。完成的方法是在另一个方法/类的单独 for 循环中设置值。该值由一个简单的方程式设置。 100 除以列表的长度,再乘以 for 循环计数器。这给了我们一个可以放入进度条值的实数。 (代码如下)

    Binder.daWindow.progUpdate = ((100.00 / databaseTables.Length) * dbTIndex);

我知道这可以通过线程(或其他)来完成,但我希望能得到专门针对如何通过绑定来完成的答案(除非不可能,然后忘记我刚才所说的)。

XAML:

<Window x:Name="DateWindow1" x:Class="WpfApp1.DateWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp1"
    xmlns:Main="using:DateWindow"
    mc:Ignorable="d"
    Title="Change Dates" Height="232.667" Width="462" Background="#FF2B2B2B" ResizeMode="NoResize">



    <Grid>
    <TextBox x:Name="DayChangeTextBox" HorizontalAlignment="Left" Height="30" Margin="176,45,0,0" TextWrapping="Wrap" Text="##" VerticalAlignment="Top" Width="58" FontSize="14" TextAlignment="Center" AcceptsReturn="False" AcceptsTab="False" GotFocus="DayChangeTextBox_GotFocus" LostFocus="DayChangeTextBox_LostFocus" BorderThickness="1" BorderBrush="Black" OpacityMask="Black" Background="#FFFDFDFD"/>
    <Label Content="Days" HorizontalAlignment="Left" Margin="239,45,0,0" VerticalAlignment="Top" Width="42" FontSize="14" FontFamily="Microsoft YaHei UI" Height="30" Foreground="White"/>
    <Label Content="Move Dates Forward:" HorizontalAlignment="Left" Margin="23,45,0,0" VerticalAlignment="Top" Width="144" FontSize="14" FontFamily="Microsoft JhengHei UI Light" Height="30" Foreground="White"/>
    <Button x:Name="ChangeDatesButton" Content="Change Dates" HorizontalAlignment="Left" Margin="303,45,0,0" VerticalAlignment="Top" Width="143" Height="30" BorderThickness="1,1,2,3" BorderBrush="#FF474747" Click="ChangeDatesButton_Click" FontFamily="Microsoft YaHei UI" Background="#FFE6E6E6"/>
    <Label x:Name="serverLabel" Content="Label" HorizontalAlignment="Left" Margin="10,73,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Width="5" Height="15" Visibility="Hidden"/>
    <Label x:Name="databaseLabel" Content="Label" HorizontalAlignment="Left" Margin="20,73,0,0" VerticalAlignment="Top" Width="3" Visibility="Hidden" Height="15"/>
    <Button x:Name="RevertToDefaultButton" Content="Revert to Backup" Margin="23,164,0,0" VerticalAlignment="Top" Height="30" Background="#FFE6E6E6" BorderBrush="#FF474747" BorderThickness="1,1,2,3" Click="RevertToDefaultButton_Click" FontFamily="Microsoft JhengHei UI" HorizontalAlignment="Left" Width="143"/>
    <Button x:Name="OverwriteDefaultButton" Content="Backup Database" Margin="23,128,0,0" VerticalAlignment="Top" Height="30" BorderBrush="#FF474747" BorderThickness="1,1,2,3" Click="OverwriteDefaultButton_Click" FontFamily="Microsoft JhengHei UI" HorizontalAlignment="Left" Width="143" Background="#FFE6E6E6" />
    <Button x:Name="CloseButton" Content="Close" Margin="0,164,10,0" VerticalAlignment="Top" Height="30" BorderBrush="#FF474747" BorderThickness="1,1,2,3" FontFamily="Microsoft JhengHei UI" Width="60" Click="CloseButton_Click" HorizontalAlignment="Right" Background="#FFE6E6E6" />
    <Label x:Name="RevertBackupLabel" Content="Backup or Revert Database:" HorizontalAlignment="Left" Margin="12,93,0,0" VerticalAlignment="Top" Foreground="White" FontFamily="Microsoft JhengHei UI" FontWeight="Bold" FontSize="16"/>
    <Label x:Name="DatesLabel" Content="Change Dates in Database:" Margin="12,10,0,0" Foreground="White" FontFamily="Microsoft JhengHei UI" FontWeight="Bold" FontSize="16" HorizontalAlignment="Left" Width="216" Height="30" VerticalAlignment="Top"/>
    <ProgressBar HorizontalAlignment="Left" Height="13" Margin="303,80,0,0" VerticalAlignment="Top" Width="143" Name="pbStatus"  Value="{Binding local.progUpdate, UpdateSourceTrigger=PropertyChanged}" Maximum="{Binding mx}" Minimum="{Binding mn}" LargeChange="0.01"/>
</Grid>

XAML CS 部分:

public static class Binder
{
    public static DateWindow daWindow;
}
public partial class DateWindow : Window, INotifyPropertyChanged
{

    private double _progUpdate;
    public double progUpdate
    {
        get { return _progUpdate; }
        set
        {
            _progUpdate = value;
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(progUpdate)));
            }

        }

    }
    public double mx = 100;
    public double mn = 0; 


    public event PropertyChangedEventHandler PropertyChanged;
    public DateWindow()
    {
        InitializeComponent();
        Binder.daWindow = this; 
        ChangeDateInDatabase ChangeDate = new ChangeDateInDatabase();
        progUpdate = 25; // This is there so we can test the variable without going through the whole program. 
    }

    private void ChangeDatesButton_Click(object sender, RoutedEventArgs e)
    {
        ChangeDateInDatabase ChangeDate = new ChangeDateInDatabase();
        var result = MessageBox.Show("Are you sure you would like to change dates for  " + Globals.selectedDatabase + " from server " + Globals.main.ServerComboBox.Text + "?", "Change Dates?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
        if (Globals.main.ServerComboBox.Text != "" && Globals.selectedDatabase != "" && FindDatabaseAndServer.Connector(Globals.main.ServerComboBox.Text, Globals.selectedDatabase) && result == MessageBoxResult.Yes)
        {
            try
            {
                long.Parse(DayChangeTextBox.Text);
                ChangeDate.ChangeDates(this); 
                //ChangeDateInDatabase.ChangeDates(this);

            }
            catch
            {
                MessageBox.Show($"Invalid number {DayChangeTextBox.Text}, please enter a valid number.", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }

(CLICK 函数的目的是为程序调用方法。在方法内部,它的主循环决定方法的完成,包含希望与定义方程绑定的变量)

包含上述循环的方法:

for (int dbTIndex = 0; dbTIndex < databaseTables.Length; dbTIndex++)
                    {
                        string[] dateColumns = new string[0];
                        string columnSelectQuery = "SELECT DATA_TYPE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS  WHERE TABLE_NAME = '" + databaseTables[dbTIndex].ToString() + "' AND COLUMN_NAME LIKE '_%'";
                        using (SqlConnection connection2 = new SqlConnection(connectionString))
                        {
                            SqlCommand command2 = new SqlCommand(columnSelectQuery, connection2);
                            connection2.Open();
                            SqlDataReader reader2 = command2.ExecuteReader();
                                int y = 0;
                                while (reader2.Read())
                                {
                                    if (reader2[0].ToString() == "datetime")
                                    {
                                        Array.Resize(ref dateColumns, dateColumns.Length + 1);
                                        dateColumns[y] = reader2[1].ToString();
                                        y++;
                                    }
                                }
                        }
                        for (var dtColIndex = 0; dtColIndex < dateColumns.Length; dtColIndex++)
                        {
                            string addDatesQuery = "UPDATE " + databaseTables[dbTIndex] + " SET " + dateColumns[dtColIndex] + " = DATEADD(dd," + Convert.ToInt32(date.DayChangeTextBox.Text) + "," + dateColumns[dtColIndex] + ") WHERE " + dateColumns[dtColIndex] + " IS NOT NULL";

                            using (SqlConnection connection3 = new SqlConnection(connectionString))
                            {
                                    SqlCommand command3 = new SqlCommand(addDatesQuery, connection3);
                                    connection3.Open();
                                    command3.ExecuteNonQuery();
                            }
                        }
                        //vvvvv VARIABLE THAT NEEDS TO BE BOUND vvvvvvv
                        Binder.daWindow.progUpdate = ((100.00 / databaseTables.Length) * dbTIndex);
                    }

(这部分显然有更多代码,如果需要我可以提供)

提前致谢!

编辑:

对于 XAML,local.progUpdate 不是我尝试过的唯一方法。我自己完成了路径、progUpdate 等。

【问题讨论】:

  • 用户解决方案:代码的问题是由滥用线程引起的。不要做我所做的,试图在不了解问题所在的情况下解决这个问题。基本了解线程的工作原理。我相信有两个可能的问题(除了绑定)。首先是工作线程过载,导致 UI 直到最后都没有改变。第二种可能性是在 UI 不理解的线程上调用 UI。也许是混合物?在循环方法中使用后台工作人员和(当前)调度程序可以解决问题。

标签: wpf binding progress-bar


【解决方案1】:

ProgressBar 的第一个绑定没有意义:{Binding local.progUpdate, UpdateSourceTrigger=PropertyChanged}。您没有指定源,也没有在任何地方分配DataContext,因此绑定不会评估任何内容,因为路径毫无意义。因为该属性位于窗口本身,所以您可以将窗口的数据上下文分配给它自己。

// DateWindow.xaml.cs
public DateWindow()
{
    InitializeComponent();
    DataContext = this;
    ...
}

<!-- DateWindow.xaml -->
<ProgressBar Value="{Binding progUpdate, Mode=OneWay}" ... />

您的其他绑定将要求 mxmn 是属性而不是字段。

【讨论】:

  • 感谢您的回答。我看到了我没有意义的地方(wpf 的新手)。我在 xaml 的 cs 中更新它,但在方法完成之前它不会在第二种方法中更新。关于如何解决这个问题的任何想法?
  • @user9622460 仅凭目测,我会说这可能是因为您在 UI 线程上反复做着重要的工作。所有PropertyChanged 事件都在触发,但是没有足够的时间来更新视图。这通常通过将繁重的工作放在另一个线程上来解决,但您必须确保在 UI 线程上更新 UI 属性progUpdate,否则不会捕获 PropertyChanged 事件。您当前的设置很混乱,因此很难区分这些问题。
  • 关于如何在不同线程中刷新 UI 有什么好的想法吗?
  • 我首先要说的是,从不同的线程更新 UI 是糟糕设计的表现。有一种方法可以做到这一点,但这只会让您的代码更难管理。排除免责声明后,请查看Dispatcher.Invoke(或异步版本,BeginInvoke)。在不同线程上最容易访问的调度程序是 System.Windows.Application.Current.Dispatcher
  • 好的!对于使代码以更易于管理的方式工作,您有什么建议?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 1970-01-01
  • 2017-07-18
  • 1970-01-01
  • 2018-01-14
  • 2012-02-10
  • 2019-03-31
相关资源
最近更新 更多