Friday, April 16, 2021

Announcing Learn WinUI 3.0 from Packt Publishing and a Contest

I'm thrilled to announce that my new book from Packt Publishing, Learn WinUI 3.0, was published in late March. You can buy your eBook or print copy today from Amazon or Packt's web site.


Windows UI (WinUI) 3 is Microsoft's next generation library for creating Windows applications with Fluent Design. WinUI 3 was released in March with Project Reunion 0.5 and is fully supported for building Win32 applications. Learn more about WinUI and Project Reunion on Microsoft Docs here.

I would like to thank Nick Randolph, who was the technical reviewer for the book. His feedback on the book's chapters and sample code were instrumental in delivering a great resource for Windows developers. I was lucky to have him involved in this project. If you aren't already following Nick's blog, go check it out now. He has been posting some great WinUI, Reunion, and Uno Platform content in recent weeks.

If you would like to win a print copy of Learn WinUI 3.0, read on. I am going to give away four copies of the book to readers of four of my blogs:

Leave a comment on this post on any of these blogs with the name of your favorite Windows or .NET development blogger. I will pick a random comment from each blog to select the four book winners. You can comment on each blog if you like, but please only comment once on each post. Comment moderation is enabled on all the blogs, so it could take a little time for your comment to appear. Make sure you sign up with a valid email address when leaving a comment. The contest closes at 11:59PM EDT on May 14th, 2021. I will ship books to winners worldwide. Please allow some time to receive the book if you are outside of the U.S.

Good luck and I hope you all enjoy my book! If you already have a copy, win one, or buy one, please leave honest ratings and reviews on Amazon. Thanks!

Tuesday, November 3, 2020

An Update on My WinUI Book from Packt Publishing

 Hello WPF fans!

I recently posted an update on my upcoming book, Learn WinUI 3, over on my WinUI Tips site. If you're looking forward to this major update from the WinUI team, go check out the blog post here.

Thanks for following, and watch for updates in the weeks ahead.

Cheers!

Alvin


Saturday, November 30, 2019

.NET Core Book Review on Morning Dew

Hello WPF developers!

I just published a book review on my Morning Dew blog that may be of interest to my readers here. C# 8.0 and .NET Core 3.0 - Modern Cross-Platform Development is a new title by Mark Price from Packt Publishing. While it covers a broad range of .NET Core topics, there are chapters on both Xamarin and Windows Desktop application development.


Go check it out here!


Friday, December 21, 2018

WPF Tip #21 - Create a Reusable ToolTip With a Header and Icon

In this tip, we're going to create a custom control derived from ToolTip to create a headered tooltip with an icon. Creating it as a custom control makes it trivial to add the tooltip to any control in your project.

This simple example will include a specific icon and has a property to hide/show the icon. I'll explain later how you could update the control's implementation to accept an icon through binding, enabling different icons across different uses.

The first step is to create the custom control class that inherits from ToolTip. Here is the implementation for HeaderedToolTip.

[TemplatePart(Name = PART_TooltipHeader, Type = typeof(TextBlock))]
[TemplatePart(Name = PART_TooltipIcon, Type = typeof(ContentControl))]
[TemplatePart(Name = PART_TooltipContents, Type = typeof(TextBlock))]
public class HeaderedToolTip : ToolTip
{
     private const string PART_TooltipHeader = "PART_TooltipHeader";
     private const string PART_TooltipIcon = "PART_TooltipIcon";
     private const string PART_TooltipContents = "PART_TooltipContents";
     private TextBlock _headerBlock = null;
     private ContentControl _iconControl = null;
     private TextBlock _contentsBlock = null;
     static HeaderedToolTip()
     {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(HeaderedToolTip), new FrameworkPropertyMetadata(typeof(HeaderedToolTip)));
     }
     public string HeaderText
     {
         get => (string)GetValue(HeaderTextProperty);
         set => SetValue(HeaderTextProperty, value);
     }
     // Using a DependencyProperty as the backing store for HeaderText. This enables animation, styling, binding, etc.
     public static readonly DependencyProperty HeaderTextProperty =
         DependencyProperty.Register("HeaderText", typeof(string), typeof(HeaderedToolTip), new UIPropertyMetadata(string.Empty));
     public string ContentText
     {
         get => (string)GetValue(ContentTextProperty);
         set => SetValue(ContentTextProperty, value);
     }
     // Using a DependencyProperty as the backing store for HeaderText. This enables animation, styling, binding, etc.
     public static readonly DependencyProperty ContentTextProperty =
         DependencyProperty.Register("ContentText", typeof(string), typeof(HeaderedToolTip), new UIPropertyMetadata(string.Empty));
     public Visibility IconVisibility
     {
         get => (Visibility)GetValue(IconVisibilityProperty);
         set => SetValue(IconVisibilityProperty, value);
     }
     // Using a DependencyProperty as the backing store for IconVisibility. This enables animation, styling, binding, etc.
     public static readonly DependencyProperty IconVisibilityProperty =
         DependencyProperty.Register("IconVisibility", typeof(Visibility), typeof(HeaderedToolTip), new UIPropertyMetadata(Visibility.Collapsed));
     public override void OnApplyTemplate()
     {
         base.OnApplyTemplate();
         _headerBlock = GetTemplateChild(PART_TooltipHeader) as TextBlock;
         _iconControl = GetTemplateChild(PART_TooltipIcon) as ContentControl;
         _contentsBlock = GetTemplateChild(PART_TooltipContents) as TextBlock;
     }
}

Some of this code is not necessary for our tooltip, but I added it here to illustrate how you can get a reference to parts of your custom control within the class in OnApplyTemplate(). This would be useful if you need to respond to any events fired from the controls that make up your custom controls. You would add the event handler hooks here after resolving them through GetTemplateChild.

The next step is to set up the template in a ResourceDictionary. Here is the XAML markup from my ToolTipResourceDictionary.xaml file.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                     xmlns:local="clr-namespace:ToolTipSample.Controls">
     <ResourceDictionary.MergedDictionaries>
         <ResourceDictionary Source="..\Images\vector_Information.xaml"/>
     </ResourceDictionary.MergedDictionaries>
     <Style TargetType="{x:Type local:HeaderedToolTip}">
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="{x:Type local:HeaderedToolTip}">
                     <Border BorderThickness="2" BorderBrush="Black">
                         <Grid Background="Ivory">
                             <Grid.RowDefinitions>
                                 <RowDefinition Height="Auto"/>
                                 <RowDefinition Height="*"/>
                             </Grid.RowDefinitions>
                             <Grid.ColumnDefinitions>
                                 <ColumnDefinition Width="*"/>
                                 <ColumnDefinition Width="Auto"/>
                             </Grid.ColumnDefinitions>
                             <TextBlock Text="{TemplateBinding HeaderText}"
                                     x:Name="PART_TooltipHeader"
                                    FontWeight="Bold"
                                    VerticalAlignment="Bottom"
                                    Margin="4"
                                    HorizontalAlignment="Left"/>
                             <ContentControl Grid.Column="1"
                                         HorizontalAlignment="Right"
                                         VerticalAlignment="Top"
                                         x:Name="PART_TooltipIcon"
                                         Content="{StaticResource vector_Information}"
                                         Visibility="{TemplateBinding IconVisibility}"
                                         Height="16" Width="16"
                                         Margin="4"/>
                             <TextBlock Grid.Row="1"
                                    Grid.ColumnSpan="2"
                                    Margin="4,12,4,6"
                                    x:Name="PART_TooltipContents"
                                    Text="{TemplateBinding ContentText}"
                                    TextWrapping="Wrap"
                                    MaxWidth="200"/>
                         </Grid>
                     </Border>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
</ResourceDictionary>

The final step is to consume our custom tooltip in a control somewhere in our project. I have create a Window containing a horizontally aligned StackPanel with two Grids. Each grid contains a border that glows a different color when you mouse over it, one blue, one gold. The second grid is disabled to demonstrate the ToolTipService.ShowOnDisabled attached property. Each Grid.ToolTip contains an instance of our HeaderedToolTip custom tooltip control.

<Window.Resources>
         <ResourceDictionary Source="..\ToolTipResourceDictionary.xaml"/>
     </Window.Resources>
     <StackPanel Orientation="Horizontal">
         <Grid ToolTipService.ShowOnDisabled="True">
             <Border Width="180" Height="180"
                 Margin="10" Background="Transparent"
                 BorderBrush="White" BorderThickness="2" Opacity="1.0">
                 <Border.Style>
                     <Style TargetType="{x:Type Border}">
                         <Style.Triggers>
                             <Trigger Property="IsMouseOver" Value="True">
                                 <Setter Property="Effect">
                                     <Setter.Value>
                                         <DropShadowEffect ShadowDepth="0" Color="Gold" Opacity="1" BlurRadius="20"/>
                                     </Setter.Value>
                                 </Setter>
                             </Trigger>
                         </Style.Triggers>
                     </Style>
                 </Border.Style>
                 <TextBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="4"/>
             </Border>
             <Grid.ToolTip>
                 <local:HeaderedToolTip HeaderText="My first fantastic header."
                                              ContentText="Some tooltip text. This could get really long."
                                              IconVisibility="Visible"/>
             </Grid.ToolTip>
         </Grid>
         <Grid IsEnabled="False" ToolTipService.ShowOnDisabled="True">
             <Border Width="180" Height="180"
                 Margin="10" Background="Transparent"
                 BorderBrush="White" BorderThickness="2" Opacity="1.0">
                 <Border.Style>
                     <Style TargetType="{x:Type Border}">
                         <Style.Triggers>
                             <Trigger Property="IsMouseOver" Value="True">
                                 <Setter Property="Effect">
                                     <Setter.Value>
                                         <DropShadowEffect ShadowDepth="0" Color="Blue" Opacity="1" BlurRadius="20"/>
                                     </Setter.Value>
                                 </Setter>
                             </Trigger>
                         </Style.Triggers>
                     </Style>
                 </Border.Style>
                 <TextBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="4"/>
             </Border>
             <Grid.ToolTip>
                 <local:HeaderedToolTip HeaderText="My second fantastic header."
                                              ContentText="Some tooltip text. This could get really, really long."
                                              IconVisibility="Collapsed"/>
             </Grid.ToolTip>
         </Grid>
     </StackPanel>

That's it. Here's a look at the tooltip in action. Please excuse my vector paragraph image in place of an actual Info icon.

custom-tooltip

Of course, in your actual implementation, data like the header's tooltip and contents will be driven from ViewModel data binding.

If you want to allow a custom icon for each use of the HeaderedToolTip, you would add an Image as another DependencyProperty on the custom control class and as another TemplatePart in the ResourceDictionary.

That's all for this WPF Tip. You can take any of these concepts and apply them to other custom controls you may need in your own applications. For more information about creating controls, check out Microsoft Docs.

Happy coding!


Saturday, October 20, 2018

Using the Rapid XAML Toolkit for Accelerating WPF Development (Preview)

Last week, I published an article on my UWP Tips blog about the Rapid XAML Toolkit.

The toolkit is for all types of XAML development, including UWP apps, Xamarin.Forms, and WPF. The toolkit is still in an early preview stage, so you will be doing a little bit of work to get up and running at first. For all the details, read my post and get started today!

Happy coding!

del.icio.us Tags: ,,

Thursday, August 9, 2018

Can I Port My Windows Desktop Application to .NET Core? Find Out and Prepare Today!

Did you know that soon you will be able to build and run your WPF (and UWP & WinForms) applications against .NET Core?

Desktop Packs

At the Microsoft Build conference in May, it was announced that the .NET team was working on some Windows-only "Desktop Packs" that could be installed on top of .NET Core v3.0. These packs would include:

  • WPF
  • WinForms
  • UWP
  • Entity Framework v6

This will bring the benefits of .NET Core to desktop client applications running on Windows. In my opinion, the biggest benefits of porting your desktop app to .NET Core will be significant performance gains and full access to Windows 10 APIs.

Obviously, in most cases, it won't be as simple as changing a project property and rebuilding your app. Project files will need to be upgraded to .NET Core format, and some legacy APIs will not be available, even in the Desktop Pack packages. This week, it has become more clear exactly which APIs will not be available in .NET Core 3.0 with Desktop Packs.

Portability Analyzer

On Wednesday, the .NET team released a Portability Analyzer tool to scan your .NET desktop applications and determine how ready they are to upgrade to .NET Core 3.0. The tool will scan your .NET binaries and dependencies and produce an Excel report (PortabilityReport.xlsx) with several tabs:

Portability Summary - This sheet contains a list of the assemblies scanned, their current .NET version target, and the % compatibility they are expected to have with .NET Core 3.0.

Details - This sheet provides details on exactly which target type and member are currently used by one of your assemblies that is not compatible with .NET Core 3.0. There is a column for Recommended Changes, but none of my incompatibilities had any recommendations.

Missing assemblies - If your assemblies reference any other assemblies which could not be resolved by the tool, they will be listed here.

My Thoughts

I ran the tool on a large application with a mix of WinForms and WPF windows. The folder contains over 900 DLLs. My thoughts:

First, I was pleasantly surprised at how fast the tool ran its analysis. It completed scanning this large application in less than a minute. I was expecting to go get a cup of coffee and a snack while it ran.

Second, the team has really included a lot of desktop APIs in these packs. I was not expecting so many of my DLLs to report at 100% compatible.

Third, many of the incompatible APIs are somewhat expected. Here are a few that came back in the report here:

  • Microsoft.VisualBasic.* - If you have VB apps, and use APIs in this namespace, expect a lot of lines to appear in your report.
  • System.Drawing.Design.* and System.Drawing.ImageConverter - Much of the System.Drawing namespaces was ported to .NET Core, but not everything. If you're doing anything advanced or uncommon, you'll probably find some issues here.
  • Things that are less common in modern development like System.Xml.XmlDataDocument, System.Runtime.Remoting.Messaging, and System.Activator.GetObject.

Console Tool

If you would prefer to run the analyzer against several applications and product individual reports for each, you can use a console analyzer with a batch file or PowerShell script instead. That version is available here, and instructions for using it are in the .NET team's post about the Portability Analyzer.

Wrap-Up

Go get your app ready for .NET Core 3.0 today! Your users will thank you later.


Tuesday, May 29, 2018

TechBash 2018 Early Bird Tickets Now Available!

4-day (with Workshop) and 3-day early bird tickets are now on sale for TechBash 2018. This year TechBash will be held October 2-5, with the 2nd being a pre-conference day of full-day workshops for 4-day ticket holders only. These workshops will be presented by top experts in each area. The topics from which to choose are ASP.NET Core 2.1, DevOps, Docker and Azure for Developers. Get more workshop info here.

Early bird tickets will save up to 25% off the Standard ticket price this year. Don't wait because these prices will only be available for a few weeks and space in each workshop is limited. This year's keynote presenter is Scott Hunter, leader of the Visual Studio and .NET Teams at Microsoft, and these other speakers have already been confirmed:

  • Jeremy Likness
  • Jessica Deen
  • Richard Taylor
  • Jeremy Clark
  • Anna Bateman
  • Brendan Enrick
  • John Wright
  • Ashley Grant
  • Ivana Veliskova
  • Steve Bohlen
  • Angel Thomas
  • Jim Wooley
  • Walt Ritscher
  • Paul Hacker
  • Jeff Fritz
  • Mitch Denny
  • Anoop Kumar

The full lineup will be announced soon. Get more info about TechBash here and buy your tickets today!

See you this fall at the Kalahari Resort in the Poconos!