Infrastructure is hard.

When you’re developing a new app, it is often daunting to decide how you’re going to structure the app.

The MVC design pattern is a well tested, and time-honored, architecture for applications of all types.

In the last few years the pattern has gained recognition through Microsoft’s ASP.NET. this is not the only technique for creating an MVC application. The MVC pattern can be implemented in any object-oriented programming language.

Today I bring you SimpleMVC. SimpleMVC is a new package for C sharp developers that provides an API they can use to create great MVC based applications. SimpleMVC uses an asynchronous programming model to allow for usage in any kind of application such as WPF, ASP.Net WinForms and even Unity or Xamarin.

MVC is not a flavor of the month. Unlike MVVM, it is capable of creating applications that are cross-platform as well as cross UI technology. Models, View definitions, and Controllers are each encapsulated so that they can be reused across different applications that need the same business logic.

SimpleMVC uses an Adapter pattern to allow models to be transported across not only platforms but data access types. Because of this you could use MS Sql Server, Oracle, or even simple mock Frameworks to provide data to your application all without changing a single line of code in the controller the model or the View.  To accomplish this I also created SimpleDI or Simple Dependency Injection.

SimpleDI allows you to create object definitions in any way you decide to define the dependency.  For example you may use the built-in JSON formatted dependency definition or you may create a hard-coded dependency definition.

All of this is about flexibility.

Conclusion:

The combination of SimpleDI an SimpleMVC allow you to create cross-platform, cross-application, and cross-technology implementations of applications that will grow with you as you need them to grow.

 

INTRODUCTION: Today a user asked a very good question on Stack Overflow about adding more data to a DataGrid as the user nears the bottom of the grid.

It was an easy enough problem to solve, so I whipped together a sample app and am writing this article to further document it.

First, you’re XAML (this time in WPF format) needs to be defined. Normal instinct would be to let the DataGrid show it’s scrollbar as necessary, but in this case you should suppress that behavior and use a ScrollViewer because the ScrollView allows you to capture a ScrollChange event and the DataGrid does not.

EXAMPLE 1

<Window x:Class="GridExpansion.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:GridExpansion"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ScrollViewer VerticalScrollBarVisibility="Visible" 
                      ScrollChanged="ScrollViewer_OnScrollChanged" 
                      PreviewMouseWheel="UIElement_OnPreviewMouseWheel">
            <DataGrid x:Name="dg" VerticalScrollBarVisibility="Disabled"></DataGrid>
        </ScrollViewer>
            <DataGrid x:Name="dg" VerticalScrollBarVisibility="Disabled"></DataGrid>
        </ScrollViewer>
    </Grid>
</Window>

Next, we need our code behind which contains the code to initialize our grid and add more data on demand.

EXAMPLE 2

using System;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace GridExpansion
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            CreateTable();

            dg.AutoGenerateColumns = true;
            dg.ItemsSource = EmployeeDataTable.DefaultView;
        }

        private DataTable employeeDataTable;
        private bool _addingData;

        public DataTable EmployeeDataTable
        {
            get { return employeeDataTable; }
            set
            {
                employeeDataTable = value;
            }
        }

        private void CreateTable()
        {
            EmployeeDataTable = new DataTable("EmployeeDataTable");
            EmployeeDataTable.Columns.Add("Row", typeof(int));
            EmployeeDataTable.Columns.Add("0", typeof(string));
            EmployeeDataTable.Columns.Add("1", typeof(string));
            EmployeeDataTable.Columns.Add("2", typeof(string));
            EmployeeDataTable.Columns.Add("3", typeof(string));
            EmployeeDataTable.Columns.Add("4", typeof(string));
            EmployeeDataTable.Columns.Add("5", typeof(string));
            EmployeeDataTable.Columns.Add("6", typeof(string));
            EmployeeDataTable.Columns.Add("7", typeof(string));
            EmployeeDataTable.Columns.Add("8", typeof(string));
            EmployeeDataTable.Columns.Add("9", typeof(string));

            GetNewData();
            GetNewData();
            GetNewData();
        }

        private void GetNewData()
        {
            for (int i = 0; i < 20; i++)//Adding 20 DataRows
            {
                var theRow = employeeDataTable.NewRow();
                theRow[0] = employeeDataTable.Rows.Count;
                for (int j = 1; j < 11; j++)
                {
                    theRow[j] = j % 2 == 0 ? "a" : "b";
                }
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
                {
                    employeeDataTable.Rows.Add(theRow);
                }));
            }
        }

        private void ScrollViewer_OnScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var sv = sender as ScrollViewer;

            if (sv != null && !_addingData)
            {
                if (sv.ScrollableHeight - e.VerticalOffset == 0)
                {
                    _addingData = true;
                    GetNewData();
                    _addingData = false;
                }
            }
        }

        private void UIElement_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            ScrollViewer scv = (ScrollViewer)sender;
            scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
            e.Handled = true;
        }
    }
}

CONCLUSION: The magic is in the ScrollViewer_OnScrollChanged event handler. We simply check if the scrollable height == the vertical height of the event args and if they are the same then we add more data.

Posted in WPF.