如何在MVVM中更改ProgressBar可见性

时间:2018-04-23 19:46:03

标签: c# wpf

ProgressBar.Visibility = Visibility.Hidden;
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectingString"].ConnectionString);

try
{

    await con.OpenAsync();
    ProgressBar.Visibility = Visibility.Hidden;
    MainWindow X= new MainWindow();
    X.Show();
    this.Close();
    con.Close();
}
catch (Exception ex)
{
    ProgressBar.Visibility = Visibility.Hidden;
    MessageBox.Show("Connection failed");
}

上面的代码表示我拥有的按钮(MVVM)的命令。但是,我不确定如何在ViewModel中为它创建一个属性(ProgressBar),仍然按照上面给出的顺序在按钮代码中调用它。

1 个答案:

答案 0 :(得分:0)

首先,我真的建议使用MVVM框架,如prism或MVVM light,因为它们提供了很多功能,例如通知UI或命令实现,如委托命令,转移到您的问题,首先,您应该移动您的业务逻辑进入您的View模型或其他层(如果您使用的是n层架构),因此您的视图模型应如下所示:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool displayProgress;

    public bool DisplayProgress
    {
        get { return displayProgress; }
        set
        {
            displayProgress = value;
            NotifyPropertyChanged();
        }
    }


    // This method is called by the Set accessor of each property.
    // The CallerMemberName attribute that is applied to the optional propertyName
    // parameter causes the property name of the caller to be substituted as an argument.
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public async Task<List<string>> LoadData()
    {
        DisplayProgress = true;
        //Here connect to the database and graph your data
        await Task.Run(() =>
        {
            Thread.Sleep(5000);//to demonstrate the delay
        });
        DisplayProgress = false;
        return new List<string>() { "A", "B", "C" };

    }
}

正如您所看到的,视图模型实现了INotifyPropertyChanged,以便在绑定属性发生变化时通知视图,就像我们要绑定到进度条中的visibility属性的显示进度条一样,并使用BooleanToVisibilityConverter,如下所示:

<Window x:Class="WpfApp2.MainWindow"
    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:WpfApp2"
    xmlns:windowsControl="clr-namespace:System.Windows.Controls;assembly=PresentationFramework"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <windowsControl:BooleanToVisibilityConverter x:Key="boolToVisibilityConverter"></windowsControl:BooleanToVisibilityConverter>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <ProgressBar  IsIndeterminate="True" Height="50" Margin="5" Visibility="{Binding Path=DisplayProgress, Converter={StaticResource boolToVisibilityConverter }}"></ProgressBar>
    <Button Name="loadButton" Grid.Row="1" Width="80" Height="40" Click="loadButton_Click">Load Data</Button>
</Grid>

如您所见,我在“System.Windows.Controls”命名空间内使用了转换器“BooleanToVisibilityConverter”(不要忘记实现它),然后将进度条可见性绑定如下:

Visibility="{Binding Path=DisplayProgress, Converter={StaticResource boolToVisibilityConverter }}"

最后我的MainWindow代码是

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private MainWindowViewModel viewModel;

    public MainWindowViewModel ViewModel
    {
        get { return viewModel; }
        set
        {
            viewModel = value;
            DataContext = viewModel;
        }
    }


    public MainWindow()
    {
        InitializeComponent();
        ViewModel = new MainWindowViewModel();
    }

    private async void loadButton_Click(object sender, RoutedEventArgs e)
    {
        var data = await ViewModel.LoadData();
        //display the data on the UI (only testing code)
        StringBuilder result = new StringBuilder();
        data.ForEach(item => result.Append($"{item},"));
        MessageBox.Show(result.ToString());
    }
}