Archive for geissingert

Adding shortcut keys to WPF Application

To add shortcut keys to a WPF application I used the following:

<Window x:Class="ProjectName.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:ProjectName"
    mc:Ignorable="d"
    Title="MainWindow" 
    Height="350" Width="525">
 
    <Window.CommandBindings>
        <CommandBinding Command="local:MainWindow.NewItem" Executed="MenuItem_Click" />
    </Window.CommandBindings>
 
    <Window.InputBindings>
        <KeyBinding Command="local:MainWindow.NewItem" Key="N" Modifiers="Ctrl" />
    </Window.InputBindings>
 
    <Grid>
        <Menu HorizontalAlignment="Stretch" VerticalAlignment="Top">
            <MenuItem Header="_File">
                <MenuItem Header="_New Item" Command="local:MainWindow.NewItem" InputGestureText="Ctrl+N" />
            </MenuItem>
        </Menu>
    </Grid>
 
</Window>

The Window.CommandBindings contains the mapping to the commands. It also has the method to execute in Executed.

The Window.InputBindings contains the mappings to the Keys used for shortcuts.

The MenuItem contains the Header as well as the Shortcut display using InputGestureText.

namespace ProjectName
{
    public partial class MainWindow : Window
    {
        public static readonly RoutedUICommand NewItem = new RoutedUICommand("NewItem", "NewItem", typeof(MainWindow));
 
        /// <summary>
        /// Shared method for MenuItems and Shortcut Keys using Commands
        /// </summary>
        /// <param name="menuItem">Name of the selected item</param>
        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            var item = string.Empty;
            var menuItem = sender as MenuItem;
            if (menuItem != null)
            {
                item = menuItem.Header.ToString();
            }
            else
            {
                // Needed to be cast to get to the ExecutedRoutedEventArgs Type
                var executedRoutedEventArgs = e as ExecutedRoutedEventArgs;
                if (executedRoutedEventArgs != null)
                {
                    item = (executedRoutedEventArgs.Command as RoutedUICommand).Text;
                }
            }
            if (!string.IsNullOrEmpty(item))
            {
                ProcessMenuItem(item);
            }
        }
 
        private void ProcessMenuItem(string menuItem)
        {
            switch (menuItem)
            {
                case "NewItem":
                    break;
                case "E_xit":
                    Application.Current.Shutdown();
                    break;
            }
        }
    }
}

The RoutedUICommand is the command that is mapped in the XAML.

The Window.CommandBindings, Window.InputBindings and the MenuItem all mapped to an item. This is how the shortcut is wired up.

The MenuItem_Click is the method that is executed when the shortcut is pressed or the menu is clicked. This method handles getting which item was chosen and passes that to the ProcessMenuItem method.

The ProcessMenuItem then processes the item as needed. As many items can be added as needed.

.Net Winform setting click event for all ToolStrip Items and MenuStrip Items

I wanted to run all click event through one method. That way I can update them as needed as well as call them from other places in the code.

After looking around I was able to use the following:

My form has a ToolStrip and a MenuStrip.

public Form1()
{
    InitializeComponent();
 
    // Get All Menu Items and all Tool Strip Buttons into a list
    var toolStripItems = toolStrip1.Items.OfType<ToolStripItem>().ToList().Union(menuStrip1.Items.GetAllToolStripMenuItems().OfType<ToolStripItem>()).ToList();
    // Set All Click Events for controls
    toolStripItems.ForEach(i => i.Click += Item_Click);
}
 
private void Item_Click(object sender, EventArgs e)
{
    ProcessMenuItem((sender as ToolStripItem).Text);
}
 
private void ProcessMenuItem(string menuItem)
{
    switch (menuItem)
    {
        case "&New":
            break;
        case "E&xit":
            Application.Exit();
            break;
    }
}

Extension Method:

public static class Extensions
{
    public static IEnumerable<ToolStripMenuItem> GetAllToolStripMenuItems(this ToolStripItemCollection toolStripItemCollection)
    {
        var toolStripMenuItems = new List<ToolStripMenuItem>();
        foreach (var toolStripItem in toolStripItemCollection.OfType<ToolStripMenuItem>())
        {
            toolStripMenuItems.Add(toolStripItem);
            toolStripMenuItems.AddRange(GetAllToolStripMenuItems(toolStripItem.DropDownItems));
        }
        return toolStripMenuItems;
    }
}

By using the above it becomes very straight forward to add what is needed by a click event.

All ToolStripItems are wired up to use and just by adding the text to the ProcessMenuItem method and the code that is needed to execute it makes it pretty straight forward to add the needed code.

Nullable SqlParameter passing a null

To pass a value that could be null use the following:

int? recordID = null;
var parameter = new System.Data.SqlClient.SqlParameter {
                    ParameterName = "@id", 
                    SqlDbType = SqlDbType.Int, 
                    Value = (object)recordID ?? DBNull.Value, 
                };

Javascript Post Data

This will post a AJAX call to the server and pass 2 items: First is an array of selected id’s and the second is a nullable int.

function updateData() {
    $.ajax({
        type: "POST",
        url: '/ControllerName/ActionName',
        datatype: "json",
        traditional: true,
        data: { ids: keys, statusID: statusID },
        success: function (data) {
            // process success here
            window.location.reload(true);
        },
        fail: function (result) {
            // process failure here
        },
    });
}

The Action on the server is as follows:

public JsonResult ActionName(List<string> ids, int? statusID)
{
    var data = "Message Retured to Client";
    return new JsonNetResult(data, JsonRequestBehavior.AllowGet);
}

Javascript Date Validation

I needed to validate a date in javascript. I am using moment in my current project. But for 2017-05-154 it failed and returned true for IsValid(). I created the following to handle validating dates.

function dateValid(dateText) {
    var valid = true;
    var year = 0;
    var month = 0;
    var day = 0;
    if (dateText) {
        var parts = dateText.split('/');
        if (parts.length == 1) {
            parts = dateText.split('-');
        }
        if (parts.length == 3) {
            if (parts[0].length == 4) {
                month = parseInt(parts[1]);
                day = parseInt(parts[2]);
                year = parseInt(parts[0]);
            }
            else if (parts[2].length == 4) {
                month = parseInt(parts[0]);
                day = parseInt(parts[1]);
                year = parseInt(parts[2]);
            }
            else {
                valid = false;
            }
            var date = new Date(year, month - 1, day);
            var dateMonth = date.getMonth() + 1;
            var dateDay = date.getDate();
            var dateYear = date.getFullYear();
            if (dateMonth != month || dateDay != day || dateYear != year) {
                valid = false;
            }
        }
        else {
            valid = false;
        }
    }
    else {
        valid = false;
    }
    return valid;
}

C# reading a CSV file and parsing with linq

I have a csv file that I need to read and wanted to parse the result using linq.

At first I was using the following:

public dynamic ReadCSVData(string path, bool firstRowFields = true)
{
    var query = from l in File.ReadAllLines(path)
                let f = l.Split(",".ToCharArray())
                select new
                {
                    Zero = f[0],
                    One = f[1],
                    Two = f[2],
                    Three = f[3],
                    Four = f[4],
                    Five = f[5],
                };
 
    return query.Skip(firstRowFields ? 1 : 0).ToList();
}

This reads data that only has the fields separated with just a comma.

The file I am reading also has fields that are enclosed with quotes.

After doing some research I came across the TextFieldParser in the Microsoft.VisualBasic.dll.

After adding the dll to the project I was able to adjust the code and now it looks as follows:

public dynamic ReadCSVData(string path, bool firstRowFields = true)
{
    dynamic data = null;
    // Have to add Microsoft.VisualBasic.dll to project
    using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(path))
    {
        parser.HasFieldsEnclosedInQuotes = true;
        parser.Delimiters = new[] { "," };
        var list = new List<string[]>();
        while (parser.PeekChars(1) != null)
        {
            string[] fields = parser.ReadFields();
            list.Add(fields);
        }
 
        var query = from f in list
                    select new
                    {
                        Zero = f[0],
                        One = f[1],
                        Two = f[2],
                        Three = f[3],
                        Four = f[4],
                        Five = f[5],
                    };
 
        data = query.Skip(firstRowFields ? 1 : 0).ToList();
    }
    return data;
}

The second method may not be usable if the file is large or fast parsing is needed.

For my project it is a small file and speed is not an issue.

This parses the file correctly as well as being part the .Net framework.

Mono Gtk Adding Widgets to a Table Widget

I am continuing to convert my application from .Net to Mono.

I am working with a table widget to layout one of my screens. After searching for a long time I was unable to find a clear way to add widgets to the table and understand where they will go.

I was finally able to figure it out and created an extension method for it.

public static void Cell(this Gtk.Table table, Gtk.Widget widget, uint row, uint column)
{
    table.Attach(widget, column, column + 1, row, row + 1);
}

When working with a table I am used to using a row and a column to add items to it.

The Attach method has 5 parameters: 1 for the widget and 4 others. After testing and working with it I was able to establish how to use row and column to add the widget to the table at the location I wanted.

.Net Create Database for SQLite

I am converting a project from Linq to Sql to Entity Framework with Sqlite.

One of the methods I was using is CreateDatabase function. When first called the function it returned the following exception:

CreateDatabase is not supported by the provider.

As I looked online most of the results mentioned to create the new structure from the existing schema.

By using the connection getschema method I noticed that the create statements are returned as a column named TABLE_DEFINITION when GetSchema is called for tables.

My end result is the following which creates a new Sqlite database with the schema from an existing database.

public class SQLiteDatabaseCreate {
    public void CreateDatabase(string newDatabase, string schemaDatabase) {
        var connectionString = string.Format("data source='{0}'", schemaDatabase);
        var dt = new System.Data.DataTable();
        using (var conn = new System.Data.SQLite.SQLiteConnection(connectionString)) {
            conn.Open();
            dt = conn.GetSchema(System.Data.SQLite.SQLiteMetaDataCollectionNames.Tables);
        }
 
        using (var conn = CreateConnectionForSchemaCreation(newDatabase)) {
            if (conn.State != System.Data.ConnectionState.Open) {
                conn.Open();
            }
            foreach (System.Data.DataRow dr in dt.Rows) {
                var createSql = dr["TABLE_DEFINITION"].ToString();
                var cmd = new System.Data.SQLite.SQLiteCommand(createSql, conn);
                cmd.ExecuteNonQuery();
            }
        }
    }
 
    public System.Data.SQLite.SQLiteConnection CreateConnectionForSchemaCreation(string filename) {
        var conn = new System.Data.SQLite.SQLiteConnection();
        conn.ConnectionString = new System.Data.Common.DbConnectionStringBuilder {
            {"Data Source", filename},
            {"Version", "3"},
            {"FailIfMissing", "False"},
        }.ConnectionString;
        conn.Open();
        return conn;
    }
}

To use it call it as follows:

var newDatabase = Path.Combine(Application.StartupPath, "NewDatabase.db");
var schemaDatabase = Path.Combine(Application.StartupPath, "SchemaDatabase.db");
var sdbc = new SQLiteDatabaseCreate();
sdbc.CreateDatabase(newDatabase, schemaDatabase);

Asp.net Master Page Image Reference

Based upon where a Master page is referenced can determine how a reference to an image needs to be. The following will maintain a consistent reference for a master page.

<img alt="Site Logo" src="<%= Page.ResolveUrl("~")%>Images/logo.jpg" />

Resize images and keep aspect ratio

I needed to store uploaded images in various sizes. It required using a max size and re-sizing it while keeping the aspect ratio.

The following is the result:

public System.Drawing.Image ResizeImage(System.Drawing.Image image, int max_size)
{
    var imageHeight = Convert.ToDouble(image.Height);
    var imageWidth = Convert.ToDouble(image.Width);
 
    // maintaining aspect ratio
    var scaleFactor = 0.0;
    var maxsize = Convert.ToDouble(max_size);
    var newWidth = Convert.ToInt32(imageWidth);
    var newHeight = Convert.ToInt32(imageHeight);
 
    // if new size is larger than original the keep original size
    if (max_size > image.Height && max_size > image.Width)
    {
        newHeight = image.Height;
        newWidth = image.Width;
    }
    else if (imageWidth >= imageHeight)
    {
        scaleFactor = maxsize / imageWidth;
        newHeight = Convert.ToInt32(imageHeight * scaleFactor);
        newWidth = max_size;
    }
    else
    {
        scaleFactor = maxsize / imageHeight;
        newWidth = Convert.ToInt32(imageWidth * scaleFactor);
        newHeight = max_size;
    }
 
    var thumbnail = new System.Drawing.Bitmap(newWidth, newHeight);
    var graphic = System.Drawing.Graphics.FromImage(thumbnail);
 
    graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
    graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
    graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
    graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
 
    graphic.DrawImage(image, 0, 0, newWidth, newHeight);
 
    return thumbnail;
}