Tuesday, July 25, 2017

WPF Tip #16 - Extended WPF Toolkit - ChildWindow & MessageBox Controls

Welcome to another Extended WPF Toolkit tip. In this tip, we will look at a couple of simple uses of the ChildWindow and MessageBox controls.

The ChildWindow control is a handy alternative to opening a separate dialog from the current application window, collecting a few pieces of data. The MessageBox operates similarly, but only presents some information and allows the user to respond, like any typical WinForm or WPF MessageBox.

In an MVVM world, opening another dialog typically either involves another View/ViewModel combination or a service to open a simple message/input dialog and return the result to the current View/ViewModel. This control is best used to replace a simple MessageBox service or when another View/ViewModel are being considered, but logically the data collected is limited and still belongs in the current ViewModel.

The use of the controls consists of a WindowContainer element containing one or more ChildWIndow and MessageBox elements. In this sample, the Window's main grid contains a WindowContainer with two ChildWindow elements and one MessageBox. They all begin with a Closed WindowState, and are opened with a button click. Here is a snippet of the view's XAML:

<StackPanel Grid.Row="2" Orientation="Horizontal" VerticalAlignment="Top">
     <Button Content="Toggle Window 1" Height="40" Width="120" Margin="2" Command="{Binding ButtonOneCommand}"/>
     <Button Content="Toggle Window 2" Height="40" Width="120" Margin="2" Command="{Binding ButtonTwoCommand}"/>
     <Button Content="Toggle Window 3" Height="40" Width="120" Margin="2" Click="ButtonBase_OnClick"/>
</StackPanel>

<tk:WindowContainer Grid.Row="2">
     <tk:ChildWindow WindowBackground="Blue"
                       Left="75"
                       Top="50"
                       Width="275"
                       Height="125" WindowState="{Binding WindowOneState}">
         <TextBlock Text="This is a child window" Padding="10"/>
     </tk:ChildWindow>

    <tk:ChildWindow WindowBackground="Green"
                       Left="175"
                       Top="125"
                       Width="275"
                       Height="125" WindowState="{Binding WindowTwoState}">
         <StackPanel>
             <TextBlock Text="This is a child window with a checkbox." Padding="10"/>
             <CheckBox Content="Check me!" Margin="8"/>
         </StackPanel>
     </tk:ChildWindow>

    <tk:MessageBox Caption="Toolkit Message" x:Name="SampleMsgBox"
                      Text="You have an alert!"/>

</tk:WindowContainer>

The MessageBox's button has a Click event handler to display the control:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
     SampleMsgBox.ShowMessageBox();
}

The two ChildWindows are opened with Commands attached to the first two buttons in our Window's ViewModel:

private void OnButtonOneClicked()
{
     if (WindowOneState == WindowState.Open)
         WindowOneState = WindowState.Closed;
     else
         WindowOneState = WindowState.Open;
    RaisePropertyChanged(nameof(WindowOneState));
}

public RelayCommand ButtonOneCommand { get; private set; }

private void OnButtonTwoClicked()
{
     if (WindowTwoState == WindowState.Open)
         WindowTwoState = WindowState.Closed;
     else
         WindowTwoState = WindowState.Open;
    RaisePropertyChanged(nameof(WindowTwoState));
}

public RelayCommand ButtonTwoCommand { get; private set; }

The ChildWindows can be closed again by using the close button on the element or by clicking it's Open button again. This second option is not available when the ChildWindow has IsModal set to true. You'll notice the WindowState property of the two ChildWindows is bound to the ViewModel. This two-way binding ensures the IF statements in the command methods will work properly regardless of how each window is closed.

Here is a look at the Window with the second ChildWindow open. This control contains a TextBlock and a CheckBox inside a StackPanel. The ChildWindow can contain only one direct child, like a Window or UserControl.

childwindows-wpf

There are tons or other uses for these controls and many properties I haven't touched on at all. Go explore them for yourself and download the toolkit today.

Happy coding!


del.icio.us Tags: ,,

Tuesday, July 18, 2017

WPF Tips Update - The Extended WPF Toolkit Has a New Home

Hello WPF fans! You may have noticed that I am a fan of Xceed's free Extended WPF Toolkit. I am actually a huge fan of free tools and productivity gains in general.

This week when I started working on WPF Tip #16, I was pleased to notice that Xceed has released v3.1 of the Extended WPF Toolkit and moved the source code from CodePlex to GitHub! The move to GitHub was, of course, motivated by Microsoft announcement that CodePlex is shutting down in the coming months.

Download, Star and Watch the Extended WPF Toolkit on GitHub

The changelog for v3.1.0 includes 37 fixes and enhancements. The Plus Edition snagged an additional 19 fixes and improvements including a Windows 10 theme, but Plus received v3.1.0 last year. It pays to pay, it seems.

wpftoolkit-github

Learn all about the toolkit on GitHub or check out WPF Tip #11. This tip was my introductory post about the controls. And be sure to stay tuned for more WPF Tips about these controls and lots more!

Happy coding!


Saturday, July 8, 2017

WPF Tip #15 - Extended WPF Toolkit - The DataGrid Control

Tip #15 is a quick detour. We'll get back to using the CalculatorUpDown control in Tip #16.

If you are looking for a quick, free way to upgrade your application's DataGrid look and behavior, the Extended WPF Toolkit includes a DataGrid which provides a significant upgrade over the WPF DataGrid in the .NET Framework.

Here is a simple Grid with a standard DataGrid in the first row and the Toolkit's DataGridControl in the second row. Both are bound to the same ItemsSource, an ObservableCollection of three fictional videos.
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
   
    <DataGrid ItemsSource="{Binding Path=MediaCatalog, IsAsync=True}"/>

    <xcdg:DataGridControl Grid.Row="1" ItemsSource="{Binding Path=MediaCatalog, IsAsync=True}"/>
</Grid>
This is what we get when running the application.


With no customization, there's a much cleaner look. You also get an improved editing experience. When clicking into the PurchaseDate column, the grid detects that the underlying data type is DateTime, and provides a Date Picker to update the value.


For more information about features available in the control, go check out the CodePlex site (migrating soon).

Happy Coding!