Replaceing the default difference/merge tool in Visual Studio with WinMerge is fairly easy, but I keep forgetting, so I figured I'd do a quick write-up.

Subversion (SVN)

After installing WinMerge, in Visual Studio, go to 

Tools -> Options -> Source Control and depending on your Source Control selection (in the case here Subversion) look for a 'Tools' menu (with Subversion its under Subversion User Tools):

If you are using Subversion/TortoiseSVN you can simply select WinMerge from the 'External Diff Tool' and 'External Merge Tool' combo boxes:

 

As always feel to ask or comment.


.RemoveWhere extension

Published 11/1/2017 by Christian

Hi All,

 

Just a quick extension this time.

This one returns an IEnumerable<T> where all source items that fulfills a given conditions has been removed.

I've called it RemoveWhere.

 

Anyway - here you are:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static IEnumerable<TSource> RemoveWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> removeSelector)
{
    List<TSource> result = new List<TSource>();
    foreach (var s in source)
    {
        if (!removeSelector(s))
        {
            result.Add(s);
        }
    }
 
    return result;
}

Can be used as:

1
WarehousePrinters = info.Printers.RemoveWhere(p => string.IsNullOrEmpty(p.PrinterID)).ToList();

As always feel to ask or comment.


Hi,

In this post I will gather my Visual Studio code snippets

First a snippet for creating a property and backing field, and raising OnPropertyChanged when the backing field has changed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="utf-8" ?>
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>proppropertychanged</Title>
            <Shortcut>proppropertychanged</Shortcut>
            <Description>Code snippet for property and backing field, and raising OnPropertyChanged when the backing field has changed</Description>
            <Author>Christian Klint Baltz Nielsen</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
                <Literal>
                    <ID>field</ID>
                    <ToolTip>The variable backing this property</ToolTip>
                    <Default>myVar</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[private $type$ $field$;
    public $type$ $property$
    {
        get { return $field$;}
        set
        {
            if($field$ != value)
            {
                $field$ = value;
                OnPropertyChanged(() => $property$);
            }
        }
    }
    $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

It will create the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
private string _imageLabel;
public string ImageLabel
{
    get { return _imageLabel; }
    set
    {
        if (_imageLabel != value)
        {
            _imageLabel = value;
            OnPropertyChanged(() => ImageLabel);
        }
    }
}

Another one for creating a 'lazy loading property' or 'self initializing property'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="utf-8" ?>
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>proplazyload</Title>
            <Shortcut>proplazyload</Shortcut>
            <Description>Code snippet for property and backing field, with initializing backing field if its null</Description>
            <Author>Christian Klint Baltz Nielsen</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
                <Literal>
                    <ID>field</ID>
                    <ToolTip>The variable backing this property</ToolTip>
                    <Default>myVar</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[private $type$ $field$;
    public $type$ $property$
    {
        get
        {
            if($field$ == null)
            {
                $field$ = new $type$();
            }
            return $field$;
        }
    }
    $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

It will create the following code:

1
2
3
4
5
6
7
8
9
10
11
12
private string _imageLabel;
public string ImageLabel
{
    get
    {
        if (_imageLabel == null)
        {
            _imageLabel = new string();
        }
        return _imageLabel;
    }
}

 

Very often I call my return variable 'result', so a snippet that 'return result' would be nice for me. Here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8" ?>
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>if</Title>
            <Shortcut>rr</Shortcut>
            <Description>Code snippet for returning result</Description>
            <Author>Christian Klint Baltz Nielsen</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
                <SnippetType>SurroundsWith</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Code Language="csharp"><![CDATA[return result; $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

and the output:

1
return result;

As always feel to ask or comment.

 


In Visual Studio (at least 2017) you can add a WPF Window to a WinForms project by slighty modifying the .csproj file.

Just add

1
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

To the end of the first

1
<PropertyGroup>

 tag.

It ends up looking something like this:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup>
    <ProjectType>Local</ProjectType>
    .
    .
    .
    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
  </PropertyGroup>
.
.
.

As always, feel free to comment, or ask.


A Simple WPF DataGrid using MVVM

Published 9/15/2017 by Christian in Code
Tags: , , ,

Her follows a simple WPF DataGrid.

In the Visual Studio Design view it look like this:

The DefaultButtonStyle and DefaultDataGrid style can be found elsewhere in this blog.

Ill include the XAML for the entire Window.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<Window x:Class="Ellab.Main.Sessions.Chamber.WPFUnitSelection.UnitSelectionView"
        xmlns:local="clr-namespace:Ellab.Main.Sessions.Chamber.WPFUnitSelection"
        mc:Ignorable="d"
        Title="{Binding Title}" x:Name="MainWindow" Height="300" Width="750">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/Ellab.WPF;component/View/Styles/ButtonStyle.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/Ellab.WPF;component/View/Styles/DataGridStyle.xaml"/>
                <ResourceDictionary Source="MvvmResources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid Background="{Binding Background, FallbackValue=Red}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <DataGrid Grid.Row="0" ItemsSource="{Binding Rows, FallbackValue=AllTheSmartRows}" Style="{StaticResource DefaultDataGrid}" HeadersVisibility="Column" AutoGenerateColumns="False" VerticalAlignment="Top" SelectionMode="Single" SelectionUnit="FullRow" SelectedItem="{Binding SelectedItem}">
            <DataGrid.RowStyle>
                <Style TargetType="{x:Type DataGridRow}">
                    <EventSetter Event="MouseLeftButtonDown" Handler="DataGrid_MouseLeftButtonDown"/>
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" Value="#FF009CDD" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.RowStyle>
            <DataGrid.Columns>
                <DataGridTextColumn Header="{Binding UnitIDHeader, FallbackValue=ID}" Binding="{Binding UnitID, FallbackValue=ID}" MinWidth="75" Width="Auto" IsReadOnly="True"/>
                <DataGridTextColumn Header="{Binding TypeHeader, FallbackValue=Type}" Binding="{Binding Type, FallbackValue=Type}" MinWidth="75" Width="Auto" IsReadOnly="True"/>
                <DataGridTextColumn Header="{Binding UnitTypeHeader, FallbackValue=Unit Type}" Binding="{Binding UnitType, FallbackValue=Unit}" MinWidth="75" Width="Auto" IsReadOnly="True"/>
                <DataGridTextColumn Header="{Binding NameHeader, FallbackValue=Name}" Binding="{Binding Name, FallbackValue=Name}" MinWidth="125" Width="Auto" IsReadOnly="True"/>
                <DataGridTextColumn Header="{Binding DescriptionHeader, FallbackValue=Description}" Binding="{Binding Description, FallbackValue=Description}" MinWidth="25" Width="*" IsReadOnly="True"/>
            </DataGrid.Columns>
        </DataGrid>
        <Grid Grid.Row="1" Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="40">
            <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right">
                <Button Margin="5" Command="{Binding HelpClickedCommand}" Width="30" Style="{StaticResource DefaultButtonStyle}" Background="#FF123F74">
                    <Image Source="../../Resources/Help.png"/>
                </Button>
                <Button Margin="5" Content="{Binding ViewButtonContent, FallbackValue=#View}" Command="{Binding ViewClickedCommand}" Style="{StaticResource DefaultButtonStyle}" Visibility="{Binding ViewVisible}" MinWidth="75"/>
                <Button Margin="5" Content="{Binding AddNewButtonContent, FallbackValue=#Add New}" Command="{Binding AddNewClickedCommand}" Style="{StaticResource DefaultButtonStyle}" Visibility="{Binding AddNewVisible}" MinWidth="75"/>
                <Button Margin="5" Content="{Binding EditButtonContent, FallbackValue=#Edit}" Command="{Binding EditClickedCommand}" Style="{StaticResource DefaultButtonStyle}" Visibility="{Binding EditVisible}" MinWidth="75"/>
                <Button Margin="5" Content="{Binding RemoveButtonContent, FallbackValue=#Remove}" Command="{Binding RemoveClickedCommand}" Style="{StaticResource DefaultButtonStyle}" Visibility="{Binding RemoveVisible}" MinWidth="75"/>
                <Button Margin="5" Content="{Binding ImportButtonContent, FallbackValue=#Import}" Command="{Binding ImportClickedCommand}" Style="{StaticResource DefaultButtonStyle}" Visibility="{Binding ImportVisible}" MinWidth="75"/>
                <Button Margin="5" Content="{Binding ExportButtonContent, FallbackValue=#Export}" Command="{Binding ExportClickedCommand}" Style="{StaticResource DefaultButtonStyle}" Visibility="{Binding ExportVisible}" MinWidth="75"/>
                <Button Margin="5" Content="{Binding OKButtonContent, FallbackValue=#OK}" Command="{Binding OKClickedCommand}" Style="{StaticResource DefaultButtonStyle}" Visibility="{Binding OKVisible}" IsDefault="True" MinWidth="75"/>
                <Button Margin="5" Content="{Binding CloseButtonContent, FallbackValue=#Close}" Command="{Binding CloseClickedCommand}" Style="{StaticResource DefaultButtonStyle}" Visibility="{Binding CloseVisible}" IsCancel="True" MinWidth="75"/>
            </StackPanel>
        </Grid>
    </Grid>
</Window>

Allthough using the MVVM design patten, I've opted to handel  event in the codebehind, as in my opinion this is View releated. Here is the event handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
namespace Ellab.Main.Sessions.Chamber.WPFUnitSelection
{
    /// <summary>
    /// Interaction logic for UnitSelectionView.xaml
    /// </summary>
    public partial class UnitSelectionView : Window
    {
        private UnitSelectionView()
        {
            InitializeComponent();
        }
 
        public UnitSelectionView(UnitSelectionViewModel mainContext)
            : this()
        {
            DataContext = mainContext;
        }
        private void DataGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DataGridRow clickedRos = sender as DataGridRow;
            clickedRos.IsSelected = true;
        }
    }
}

As always, feel free to comment, or ask.


The System.Linq.Distinct extension returns a list (or more to the point, an IEnumerable<>) of ... surprise ... distinct items in a list.

This is all well and good for simple data types (e.g. integers). But what if you have more complex data types, and you want to get a distinct list based on a specific property.

Well - Distinct extension enumerates the Object.Equals method on all items in the list, and returns a new list list based on the result. An object is only equal to another object if they have the same hash code. So running List<T>.Distinct() would only exclude items from List<T> where T are the same object, and not items with the same information.

Say you have a Student type:

1
2
3
4
5
6
7
8
9
10
11
public class Student
{
    public long ID { get; set; }
    public string Name { get; set; }
 
    public Student(long id, string name)
    {
        ID = id;
        Name = name;
    }
}

And a Class:

1
2
3
4
public class Class
{
    private List<Student> _students { get; } = new List<Student>() { new Student(1, "John Doe"), new Student(1, "John Doe"), new Student(2, "Jane Doe") };
}

Running 

1
IEnumerable<Student> distinctStudent = _students.Distinct();

would give you 3 items, as both "John Doe" have unique HashCode - they are not the same object.

There are two ways of getting about this.

Either override Object.Equals(object obj) and Object.GetHashCode() on the Student type:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Student
{
    public long ID { get; set; }
    public string Name { get; set; }
 
    public Student(long id, string name)
    {
        ID = id;
        Name = name;
    }
 
    public override bool Equals(object obj)
    {
        var student = obj as Student;
        return this.ID.Equals(student?.ID);
    }
    public override int GetHashCode()
    {
        return ID.GetHashCode();
    }
    public override string ToString()
    {
        return Name;
    }
}

This executes fairly fast, but you would only be able to get unique items based on their ID.

If you want a more customisable way, you could write an extension:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static class Extensions
{
    public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
    {
        HashSet<TKey> seenKeys = new HashSet<TKey>();
        foreach (TSource item in source)
        {
            if (seenKeys.Add(keySelector(item)))
            {
                yield return item;
            }
        }
    }
}

and user it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Class
{
    private List<Student> _students { get; } = new List<Student>() { new Student(1, "John Doe"), new Student(1, "John Doe"), new Student(2, "Jane Doe") };
 
    public IEnumerable<Student> GetDistinct()
    {
        return _students.Distinct();
    }
 
    public IEnumerable<Student> GetDistinctBy()
    {
        return _students.DistinctBy(s => s.ID);
    }
 
    public IEnumerable<Student> GetDistinctByMore()
    {
        return _students.DistinctBy(s => new { s.ID, s.Name });
    }
}

As always, feel free to comment, or ask.


You can delete a TFS branch from the Visual Studio Developer Command Prompt, using the 'tf destroy' command. The syntax is as follows:

C:\tf delete $/TeamProject/Branch

This is also valid for folder or files.

C:\tf delete $/MyTeamProject/Folder
C:\tf delete $/MyTeamProject/Folder/File

Of course remember to put any Branch/Folder/Files with spaces in, inside quotes:

C:\tf delete $/MyTeamProject/"Branch No 1" 

As always, feel free to comment, or ask.

Getting an ancestor property value can be done by binding to its element name. Here's an example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<Grid Width="{Binding Width}" Margin="{Binding Margin}">
    <Border BorderBrush=" #FF17447E" BorderThickness="5">
        <StackPanel Name="MainStackPanel" Orientation="Vertical">
            <ScrollViewer Height="{Binding ElementName=MainStackPanel, Path=ActualHeight}">
                <ItemsControl ItemsSource="{Binding Rows, FallbackValue=Rows}" Background="Transparent">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Vertical"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <ContentPresenter Content="{Binding}" Height="30"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </ScrollViewer>
        </StackPanel>
    </Border>
</Grid>

As always, feel free to comment, or ask


Exciting new stuff for C# 7

Published 4/11/2016 by Christian

Sounds like there are som exciting new stuff in waiting for C# programmers.

Personally, I've never like tuples, but it looks like they are going to make sense, since you can now give the var's names.

Anyway - a link to the 2016 build presentation: https://channel9.msdn.com/events/build/2016/b889

And here is another from the Visual Studio 2017 Launch: https://channel9.msdn.com/Events/Connect/2016/105?ocid=player

More from the VS2017 Launch: https://channel9.msdn.com/Events/Visual-Studio/Visual-Studio-2017-Launch/140

 

 

 


WPF Controls has no ‘InvokeRequired’/’Invoke’ like WinForms, so making accessing a WPF Window/Control threadsafe can be accomplished by using the System.Windows.Threading.Dispatcher. Here are some examples. First a property: 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public int Progress
{
    get
    {
        if (!Dispatcher.CheckAccess())
        {
            Func<int> f = delegate () { return Progress; };
            return Dispatcher.Invoke(f);
        }
 
        ...
    }
    set
    {
        if (!Dispatcher.CheckAccess())
        {
            Action<int> a = delegate (int progress) { Progress = progress; };
            Dispatcher.Invoke(a);
            return;
        }
 
        ...
    }
}

 

  A void method

 

 

1
2
3
4
5
6
7
8
9
10
11
public void SetProgress(object obj, int progress)
{
    if (!Dispatcher.CheckAccess())
    {
        Action<object, int> a = new Action<object, int>(SetProgress);
        Dispatcher.Invoke(a, DispatcherPriority.Normal, obj, progress);
        return;
    }
 
    ...
}

 

And lastly a method with a return value

 

 

1
2
3
4
5
6
7
8
9
10
public bool AllProcessesDone()
{
    if (!Dispatcher.CheckAccess())
    {
        Func<bool> f = new Func<bool>(AllProcessesDone);
        return Dispatcher.Invoke(f, DispatcherPriority.Normal);
    }
 
    ...
}

 

As always, feel free to comment, or ask.