2
\$\begingroup\$

I'm new to C#, WPF and MVVM and I don't want to make common mistakes right from the beginning and get used to them. I already read some similar questions on best practices for WPF/MVVM but none of them included async/await patterns.

I'm also using MahApps.Metro for UI and MVVM.Light Toolkit.

MainWindow.xaml (cropped)

[...]
 <Grid>
            <TabControl Controls:TabControlHelper.Underlined="TabPanel">
                <TabItem Header="Programs">
                    <Grid DataContext="{Binding ProgramsViewModelMain, Source= {StaticResource Locator}}">
                        <Button  Content="Refresh" Command="{Binding LoadDataBase}" Height="10" Width="100" VerticalAlignment="Top" HorizontalAlignment="Right"/>
                        <Controls:ProgressRing IsActive="{Binding IsLoading}" DockPanel.Dock="Top" Height="60" Width="60" Margin="0 10 0 0"/>
                        <DataGrid Margin="0 25 0 0" EnableRowVirtualization="True" GridLinesVisibility="All" Grid.ColumnSpan="2" ItemsSource="{Binding OfsItems}" AutoGenerateColumns="False">
                            <DataGrid.Columns>
                                <DataGridTextColumn Binding="{Binding ProductionOrder}" Header="Production Order"/>
                                <DataGridTextColumn Binding="{Binding OfsTask}" Header="Task"/>
                            </DataGrid.Columns>
                            <DataGrid.Style>
                                <Style TargetType="DataGrid" BasedOn="{StaticResource MetroDataGrid}">
                                    <Setter Property="Visibility" Value="Hidden"/>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding IsLoading}" Value="False">
                                            <Setter Property="Visibility" Value="Visible"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </DataGrid.Style>
                        </DataGrid>
                    </Grid>
                </TabItem>
[...]

Model

using GalaSoft.MvvmLight;
using System.Data.Odbc;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace CPM_WPF.Model
{
  public class Ofs : ObservableObject
  {
    public async Task<ObservableCollection<OfsItem>> GetOfsItemsAsync()
    {
        ObservableCollection<OfsItem> ofsdata = new ObservableCollection<OfsItem>();
        List<OfsItem> ofslist = new List<OfsItem>();

        ofslist = await Task.Run(() => DonwloadOfsData()); //get items from database

        foreach (var item in ofslist) //list to observablecollection
        {
            ofsdata.Add(item);
        }
        return ofsdata;       
    }

    private List<OfsItem> DonwloadOfsData()
    {
        List<OfsItem> ofslist = new List<OfsItem>();

        OdbcConnection cn;
        OdbcCommand cmd;
        OdbcDataReader dr;

        //connect to database
        string query;
        query = "Select * from tblProductionOrders WHERE Task = 2830";
        cn = new OdbcConnection("Driver={SQL Server};Server=LUDUDSVPSQL1201;Database=OFS460;");
        cmd = new OdbcCommand(query, cn);
        cn.Open();

        dr = cmd.ExecuteReader();

        //read values
        while (dr.Read())
        {
            ofslist.Add(new OfsItem //add items to list
            {
                ProductionOrder = dr.GetInt32(1),
                OfsTask = dr.GetInt32(6)
            });
        };
        return ofslist;
    }

}
public class OfsItem : ObservableObject
{
    private int po;
    private int ofsTask;
    public int ProductionOrder
    {
        get => po;            
        set => Set<int>(() => this.ProductionOrder, ref po, value);
    }
    public int OfsTask
    {
        get => ofsTask;           
        set => Set<int>(() => this.OfsTask, ref ofsTask, value);           
    }   
  }
}

ViewModel

using CPM_WPF.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows.Input;

namespace CPM_WPF.ViewModel
{
  public class ProgramsViewModel : ViewModelBase
  {
    public ICommand LoadDataBase { get; private set; }
    public ProgramsViewModel()
    {
        LoadDataBase = new RelayCommand(async () => await LoadDataBaseMethod());
    }

    public async Task LoadDataBaseMethod()
   {
        IsLoading = true;
        Ofs ofs = new Ofs();
        OfsItems = await Task.Run(() => ofs.GetOfsItemsAsync());
        IsLoading = false;
    }

    private ObservableCollection<OfsItem> ofsItems;
    private bool isLoading;

    public bool IsLoading
    {
        get => isLoading; 
        set => Set<bool>(() => this.IsLoading, ref isLoading, value);           
    }

    public ObservableCollection<OfsItem> OfsItems
    {
        get => ofsItems;
        set => Set<ObservableCollection<OfsItem>>(() => this.OfsItems, ref ofsItems, value); 
    }
  }
}
\$\endgroup\$
  • 4
    \$\begingroup\$ Before we can review your code you need to tell us what it is about. Please edit your question and add a description and explain your code in more detail. \$\endgroup\$ – t3chb0t Mar 4 '19 at 15:09