StyleMyImage.com Programming Blog

Exploration of Big Data, Machine Learning, Natural Language Processing, and other fun problems.

Use C# to loop through all Enum Values

Suppose you have an enum with several values like this:

public enum EnumValues
{
EFirst,
ESecond,
EThird
};

And you want to do a foreach(var enumValue in EnumValues). How do you do that?


There is a GetValues method that you can use like this:

var enumValues = Enum.GetValues(typeof(EnumValues));

Or you can use typed version like this:

var enumValues = Enum.GetValues(typeof(EnumValues)).Cast<EnumValues>();

Then, you can write your foreach using the enumValues collection like this:

foreach(enumValue in enumValues)
{
    ...
}


How to do a multiple OrderBy in LINQ across two tables.

This article will show example solutions to accomplish multiple OrderBy commands in one query in LINQ across multiple tables.


Table 1: Movies

Columns: MovieID, MovieName, and CategoryID (FK to Categories table)


Table 2: Categories

Columns: CategoryID, CategoryName


Goal: We want to select movies and order the records first by CategoryName and secondly by MovieName.


First, we can select movies and order them by CategoryName like this:

var movieRecords = dbContext.Movies.OrderBy(c => c.CategoryName);

Next, we introduce the ThenBy function and apply it to our query like this:

var movieRecords = dbContext.Movies.OrderBy(c => c.CategoryName).ThenBy(m => m.MovieName)

When we iterate through the resulting movieRecords, the items will be ordered by CategoryName and MovieName.


Another approach to accomplishing the multiple order by query without using Lambda expressions can look like this:

var movieRecords = from movieRecord in dbContext.Movies 
             orderby movieRecord.MovieCategory, movieRecord.MovieName
             select movieRecord;

Simply, separate the order by columns with a comma and write a from X orderby and select LINQ statement like the above example.


Reading an Excel file in C# using EPPlus

I had written a post about using EPPlus for writing Excel formatted reports in a previous blog article that you can find here: 

Creating an Excel report with C# using a MySql data source

What if we want to read an Excel file source? Can we still use EPPlus? Yes!


First, add the EPPlus nuget package to your Visual Studio project.



Next, create an ExcelPackage handle and open your source Excel file like this. You can access worksheets in your workbook like the below code.

                ExcelPackage package = new ExcelPackage(new FileInfo(sourceExcelFile));
                ExcelWorksheet workSheet = package.Workbook.Worksheets[1];

Note that most things in EPPlus are indexed as 1 to N rather than 0 to N-1. Accessing Worksheets[1] is the first worksheet. Accessing column[1] is the first column, and row[1] is the first row.


Now, we want to iterate and access our worksheet cell data. We can iterate and access our worksheet cell data like this:

for (int rowIndex = workSheet.Dimension.Start.Row; rowIndex <= workSheet.Dimension.End.Row; rowIndex++)
{
for (int colIndex = workSheet.Dimension.Start.Column; colIndex <= workSheet.Dimension.End.Column; colIndex++)
{
// You can access cells directly like this:
string myCellText = workSheet.Cells[rowIndex, colIndex].Text;
}
}

Warning: The workSheet.Dimension.End.Row value is sometimes not what you expect. Your source Excel file could have 100 rows, and workSheet.Dimension.End.Row may still be a value of 1 million. You will probably want to add some code to validate your cells and break the loop when your records are done being processed.


Another way to work with the cells is to get its value with a .Value.ToString() call like this:

		string myCellText = workSheet.Cells[rowIndex, colIndex].Text;
string myCellText = workSheet.Cells[rowIndex, colIndex].Value.ToString();

Most of the time the .Text and .Value.ToString() will be the same result, but not always. On case I encountered was with date columns. The .Text resulted in a nice "5/16/2017" output, and the .Value.ToString() was giving me an unexpected number like "43340".


Dynamically scale Height and Width for a WebView control in XAML C#

We are writing a Universal Windows Platform application with a UI that is XAML with C#, but I wan't to have a WebView control that just loads up a web page. The WebView control appears to not allow height and width to be "Auto" or "100%", and if we delete the height and width it defaults to 0 values. How do we fix this?


Drop a WebView on your designer and XAML is generated that looks like this:

            <WebView x:Name="WebView1" HorizontalAlignment="Left" Height="475" Margin="10,64,0,0" Grid.Row="1" VerticalAlignment="Top" Width="245" LoadCompleted="WebView_LoadCompleted"/>
Note that it defaults with a fixed height and width value, which is almost never going to be what we want for responsive Universal Windows Platform applications.

I've also given our WebView an x:Name="WebView1" value, so we can reference our instance in the code behind.

In our code behind, we'll also load up a web page in to our WebView control. We'll keep this simple and just load our WebView after calling InitializeComponent. Notice that we use the WebView1 instance name that the XAML instantiates and initializes for us.

        public MainPage()
        {
            InitializeComponent();
            // Attempt to navigate to the specified URL.  Notice that a malformed URL will raise a FormatException
            // which we catch and let the user know that the URL is bad and to enter a new well-formed one.
            try
            {
                Uri targetUri = new Uri("http://StyleMyImage.com");
                WebView1.Navigate(targetUri);
            }
            catch (FormatException exception)
            {
                // Handle errors here
            }
        }

Perhaps you've already tried to edit the height and width to your WebView hoping for an "auto" or "100%" behavior. If not, I encourage you to try to edit the WebView and try that. The trick we'll use to solve this is that our WebView lives inside a Grid control. We will put a SizeChanged event handler on our Grid control by typing in a SizeChanged="Grid_SizeChanged" like this:

        <Grid 
            x:Name="Grid1"
            SizeChanged="Grid_SizeChanged"
            Grid.Row="1" 
            Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
            <WebView x:Name="WebView1" HorizontalAlignment="Left"  Margin="10,64,0,0" Grid.Row="1" VerticalAlignment="Top" LoadCompleted="WebView_LoadCompleted"/>
        </Grid>

Then, in our code behind we'll add a function to implement the Grid_SizeChanged event like this:
        private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            double remainingWidth = Windows.UI.Xaml.Window.Current.Bounds.Width;
            WebView1.Width = remainingWidth;
            WebView1.Height = e.NewSize.Height;
        }
Now, you're WebView control should fill the full height and width of your grid control dynamically. When your Grid control changes height and width, then you're WebView control will also change. 

Here's the result of my Universal Windows Platform application with a simple WebView control to load StyleMyImage.com: