tag:blogger.com,1999:blog-9598527665539981742024-02-20T13:10:17.484-05:00WPF TipsWPF Tips for Microsoft Visual Studio and .NET developers. Take your XAML skills up a notch.Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-959852766553998174.post-56985306390162570952021-04-16T10:00:00.000-04:002021-04-16T10:00:00.233-04:00Announcing Learn WinUI 3.0 from Packt Publishing and a Contest<p>I'm thrilled to announce that my new book from <a href="https://www.packtpub.com/">Packt Publishing</a>, Learn WinUI 3.0, was published in late March. You can buy your eBook or print copy today from <a href="https://www.amazon.com/Learn-WinUI-3-0-application-development/dp/1800208669/">Amazon</a> or Packt's <a href="https://www.packtpub.com/product/learn-winui-3-0/9781800208667">web site</a>.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://www.alvinashcraft.com/wp-content/uploads/2021/01/learnwinui.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="218" data-original-width="177" src="https://www.alvinashcraft.com/wp-content/uploads/2021/01/learnwinui.jpg" /></a></div><br /><p><a href="https://github.com/Microsoft/microsoft-ui-xaml">Windows UI</a> (WinUI) 3 is Microsoft's next generation library for creating Windows applications with <a href="https://www.microsoft.com/design/fluent/#/">Fluent Design</a>. WinUI 3 was released in March with <a href="https://github.com/microsoft/ProjectReunion">Project Reunion</a> 0.5 and is fully supported for building Win32 applications. Learn more about WinUI and Project Reunion on Microsoft Docs <a href="https://docs.microsoft.com/en-us/windows/apps/project-reunion/">here</a>.</p>
<p>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 <a href="https://nicksnettravels.builttoroam.com/">Nick's blog</a>, go check it out now. He has been posting some great WinUI, Reunion, and Uno Platform content in recent weeks.</p>
<p>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:</p>
<ul>
<li>The Morning Dew - <a href="https://www.alvinashcraft.com">www.alvinashcraft.com</a></li>
<li>UWP Tips - <a href="https://www.uwpapp.tips">www.uwpapp.tips</a></li>
<li>WPF Tips - <a href="https://www.wpf.tips">www.wpf.tips</a></li>
<li>WinUI Tips - <a href="https://www.winui.tips">www.winui.tips</a></li>
</ul>
<p>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.</p>
<p>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!</p>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com4tag:blogger.com,1999:blog-959852766553998174.post-54193989836991865302020-11-03T07:56:00.001-05:002020-11-03T07:56:13.141-05:00An Update on My WinUI Book from Packt Publishing<p> Hello WPF fans!</p><p>I recently posted an update on my upcoming book, Learn WinUI 3, over on my <a href="https://www.winui.tips/" target="_blank">WinUI Tips</a> site. If you're looking forward to this major update from the WinUI team, go check out the blog post <a href="https://www.winui.tips/2020/09/an-update-on-my-book-learn-winui-30.html">here</a>.</p><p>Thanks for following, and watch for updates in the weeks ahead.</p><p>Cheers!</p><p>Alvin</p><p><br /></p><script src="chrome-extension://joojdhbnigbkaeaohmookbghmlfejcpm/notify/inject.js"></script>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-6344238171499157102019-11-30T12:27:00.002-05:002019-11-30T12:27:46.905-05:00.NET Core Book Review on Morning DewHello WPF developers!<br />
<br />
I just published a book review on my <a href="https://www.alvinashcraft.com/">Morning Dew blog</a> 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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNifPBdj_2FI1X0xIzdQeyfr8XgiWx0d2y3qaeXD1GD0FGSQsLzuOOB6az9QisyewLCx_PEP_A1ovPn8ZDGuVMYi-87ABbP7gAYyw1E3jVLPB9dkO5PIqbJw489BbXSmAOMcTDrkeBk1tA/s1600/price-dotnetcore.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="424" data-original-width="348" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNifPBdj_2FI1X0xIzdQeyfr8XgiWx0d2y3qaeXD1GD0FGSQsLzuOOB6az9QisyewLCx_PEP_A1ovPn8ZDGuVMYi-87ABbP7gAYyw1E3jVLPB9dkO5PIqbJw489BbXSmAOMcTDrkeBk1tA/s320/price-dotnetcore.png" width="262" /></a></div>
<br />
Go check it out <a href="https://www.alvinashcraft.com/2019/11/30/the-dew-review-c-8-0-and-net-core-3-0-modern-cross-platform-development-packt-by-mark-j-price/">here</a>!<br />
<br />
<br />Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-32337513803960075452018-12-21T09:48:00.001-05:002018-12-21T09:48:40.763-05:00WPF Tip #21 - Create a Reusable ToolTip With a Header and Icon<p>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.</p><p>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.</p><p>The first step is to create the custom control class that inherits from ToolTip. Here is the implementation for HeaderedToolTip.</p><pre class="brush: csharp">[TemplatePart(Name = PART_TooltipHeader, Type = typeof(TextBlock))]<br>
[TemplatePart(Name = PART_TooltipIcon, Type = typeof(ContentControl))]<br>
[TemplatePart(Name = PART_TooltipContents, Type = typeof(TextBlock))]<br>
public class HeaderedToolTip : ToolTip
<br>{<br> private const string PART_TooltipHeader = "PART_TooltipHeader";<br> private const string PART_TooltipIcon = "PART_TooltipIcon";<br> private const string PART_TooltipContents = "PART_TooltipContents";<br> private TextBlock _headerBlock = null;<br> private ContentControl _iconControl = null;<br> private TextBlock _contentsBlock = null;<br> static HeaderedToolTip()<br> {<br> DefaultStyleKeyProperty.OverrideMetadata(typeof(HeaderedToolTip), new FrameworkPropertyMetadata(typeof(HeaderedToolTip)));<br> }<br> public string HeaderText<br> {<br> get => (string)GetValue(HeaderTextProperty);<br> set => SetValue(HeaderTextProperty, value);<br> }<br> // Using a DependencyProperty as the backing store for HeaderText. This enables animation, styling, binding, etc.<br> public static readonly DependencyProperty HeaderTextProperty =<br> DependencyProperty.Register("HeaderText", typeof(string), typeof(HeaderedToolTip), new UIPropertyMetadata(string.Empty));<br> public string ContentText<br> {<br> get => (string)GetValue(ContentTextProperty);<br> set => SetValue(ContentTextProperty, value);<br> }<br> // Using a DependencyProperty as the backing store for HeaderText. This enables animation, styling, binding, etc.<br> public static readonly DependencyProperty ContentTextProperty =<br> DependencyProperty.Register("ContentText", typeof(string), typeof(HeaderedToolTip), new UIPropertyMetadata(string.Empty));<br> public Visibility IconVisibility<br> {<br> get => (Visibility)GetValue(IconVisibilityProperty);<br> set => SetValue(IconVisibilityProperty, value);<br> }<br> // Using a DependencyProperty as the backing store for IconVisibility. This enables animation, styling, binding, etc.<br> public static readonly DependencyProperty IconVisibilityProperty =<br> DependencyProperty.Register("IconVisibility", typeof(Visibility), typeof(HeaderedToolTip), new UIPropertyMetadata(Visibility.Collapsed));<br> public override void OnApplyTemplate()<br> {<br> base.OnApplyTemplate();<br> _headerBlock = GetTemplateChild(PART_TooltipHeader) as TextBlock;<br> _iconControl = GetTemplateChild(PART_TooltipIcon) as ContentControl;<br> _contentsBlock = GetTemplateChild(PART_TooltipContents) as TextBlock;<br> }<br>
}</pre><p>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.</p><p>The next step is to set up the template in a ResourceDictionary. Here is the XAML markup from my ToolTipResourceDictionary.xaml file.</p><pre class="brush: xml"><ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"<br> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"<br> xmlns:local="clr-namespace:ToolTipSample.Controls"><br> <ResourceDictionary.MergedDictionaries><br> <ResourceDictionary Source="..\Images\vector_Information.xaml"/><br> </ResourceDictionary.MergedDictionaries><br> <Style TargetType="{x:Type local:HeaderedToolTip}"><br> <Setter Property="Template"><br> <Setter.Value><br> <ControlTemplate TargetType="{x:Type local:HeaderedToolTip}"><br> <Border BorderThickness="2" BorderBrush="Black"><br> <Grid Background="Ivory"><br> <Grid.RowDefinitions><br> <RowDefinition Height="Auto"/><br> <RowDefinition Height="*"/><br> </Grid.RowDefinitions><br> <Grid.ColumnDefinitions><br> <ColumnDefinition Width="*"/><br> <ColumnDefinition Width="Auto"/><br> </Grid.ColumnDefinitions><br> <TextBlock Text="{TemplateBinding HeaderText}"<br> x:Name="PART_TooltipHeader"<br> FontWeight="Bold"<br> VerticalAlignment="Bottom"<br> Margin="4"<br> HorizontalAlignment="Left"/><br> <ContentControl Grid.Column="1"<br> HorizontalAlignment="Right"<br> VerticalAlignment="Top"<br> x:Name="PART_TooltipIcon"<br> Content="{StaticResource vector_Information}"<br> Visibility="{TemplateBinding IconVisibility}"<br> Height="16" Width="16"<br> Margin="4"/><br> <TextBlock Grid.Row="1"<br> Grid.ColumnSpan="2"<br> Margin="4,12,4,6"<br> x:Name="PART_TooltipContents"<br> Text="{TemplateBinding ContentText}"<br> TextWrapping="Wrap"<br> MaxWidth="200"/><br> </Grid><br> </Border><br> </ControlTemplate><br> </Setter.Value><br> </Setter><br> </Style><br>
</ResourceDictionary></pre><p>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.</p><pre class="brush: xml"><Window.Resources><br> <ResourceDictionary Source="..\ToolTipResourceDictionary.xaml"/><br> </Window.Resources><br> <StackPanel Orientation="Horizontal"><br> <Grid ToolTipService.ShowOnDisabled="True"><br> <Border Width="180" Height="180"<br> Margin="10" Background="Transparent"<br> BorderBrush="White" BorderThickness="2" Opacity="1.0"><br> <Border.Style><br> <Style TargetType="{x:Type Border}"><br> <Style.Triggers><br> <Trigger Property="IsMouseOver" Value="True"><br> <Setter Property="Effect"><br> <Setter.Value><br> <DropShadowEffect ShadowDepth="0" Color="Gold" Opacity="1" BlurRadius="20"/><br> </Setter.Value><br> </Setter><br> </Trigger><br> </Style.Triggers><br> </Style><br> </Border.Style><br> <TextBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="4"/><br> </Border><br> <Grid.ToolTip><br> <local:HeaderedToolTip HeaderText="My first fantastic header."<br> ContentText="Some tooltip text. This could get really long."<br> IconVisibility="Visible"/><br> </Grid.ToolTip><br> </Grid><br> <Grid IsEnabled="False" ToolTipService.ShowOnDisabled="True"><br> <Border Width="180" Height="180"<br> Margin="10" Background="Transparent"<br> BorderBrush="White" BorderThickness="2" Opacity="1.0"><br> <Border.Style><br> <Style TargetType="{x:Type Border}"><br> <Style.Triggers><br> <Trigger Property="IsMouseOver" Value="True"><br> <Setter Property="Effect"><br> <Setter.Value><br> <DropShadowEffect ShadowDepth="0" Color="Blue" Opacity="1" BlurRadius="20"/><br> </Setter.Value><br> </Setter><br> </Trigger><br> </Style.Triggers><br> </Style><br> </Border.Style><br> <TextBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="4"/><br> </Border><br> <Grid.ToolTip><br> <local:HeaderedToolTip HeaderText="My second fantastic header."<br> ContentText="Some tooltip text. This could get really, really long."<br> IconVisibility="Collapsed"/><br> </Grid.ToolTip><br> </Grid><br> </StackPanel></pre><p>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.</p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVi9-G1nYgoWDwTWOSNEDAG5BmIRP7AZiImpDoUWD56-J0V893o1t8rUXIKVnTD8W2-QM-sjpBlzI4rAtNIPsQY86J1e1Ob3cCfV5oIbdeQgIoqt67n1w24B2h_iIUt4svu_G4bk5C9mWy/s1600-h/custom-tooltip%255B5%255D"><img width="482" height="272" title="custom-tooltip" style="border: 0px currentcolor; border-image: none; display: inline; background-image: none;" alt="custom-tooltip" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIPlZc_aa8pD37scsvlm084YhuUZjQkYPvsU5asAu6hNw1cdYfD2XTf_Cp06OjTju6H5IuHWGQy7Glzimz3YO376Z5H-iSn6LPpTHP7h2dZ2YkFlQzf6yuDgxZ-uAWbitqkxhVkcyEEYij/?imgmax=800" border="0"></a></p><p>Of course, in your actual implementation, data like the header's tooltip and contents will be driven from ViewModel data binding.</p><p>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.</p><p>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 <a href="https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/control-authoring-overview?wt.mc_id=MVP" target="_blank">Microsoft Docs</a>.</p><p>Happy coding!</p><p><br></p><div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:7109d0b2-c374-4cc4-bc5f-179393208964" style="margin: 0px; padding: 0px; float: none; display: inline;">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/custom+controls" rel="tag">custom controls</a>,<a href="http://del.icio.us/popular/template+binding" rel="tag">template binding</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-20421382898418730072018-10-20T10:22:00.002-04:002018-10-20T10:22:24.337-04:00Using the Rapid XAML Toolkit for Accelerating WPF Development (Preview)Last week, I published an article on my <a href="https://www.uwpapp.tips/">UWP Tips</a> blog about the <a href="https://github.com/Microsoft/Rapid-XAML-Toolkit">Rapid XAML Toolkit</a>.<br />
<br />
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, <a href="https://www.uwpapp.tips/2018/10/uwp-tips-early-look-rapid-xaml-toolkit.html">read my post</a> and get started today!<br />
<br />
<i>Happy coding!</i><br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:577db837-322f-4dd2-b0b6-b664b2ee2ee5" style="display: inline; float: none; margin: 0px; padding: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/uwp" rel="tag">uwp</a>,<a href="http://del.icio.us/popular/rapid+xaml+toolkit" rel="tag">rapid xaml toolkit</a>,<a href="http://del.icio.us/popular/mvvm" rel="tag">mvvm</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-76247312077647017022018-08-09T10:42:00.001-04:002018-08-09T10:42:53.987-04:00Can I Port My Windows Desktop Application to .NET Core? Find Out and Prepare Today!<p>Did you know that soon you will be able to build and run your WPF (and UWP & WinForms) applications against .NET Core?</p><h3>Desktop Packs</h3><p>At the <a href="https://developer.microsoft.com/en-us/events/build" target="_blank">Microsoft Build</a> conference in May, it was <a href="https://blogs.msdn.microsoft.com/dotnet/2018/05/07/net-core-3-and-support-for-windows-desktop-applications/" target="_blank">announced</a> 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:</p><ul><li>WPF</li><li>WinForms</li><li>UWP</li><li>Entity Framework v6</li></ul><p>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 <a href="https://blogs.msdn.microsoft.com/dotnet/2018/04/18/performance-improvements-in-net-core-2-1/" target="_blank">performance gains</a> and full access to Windows 10 APIs.</p><p>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.</p><h3>Portability Analyzer</h3><p>On Wednesday, the .NET team <a href="https://blogs.msdn.microsoft.com/dotnet/2018/08/08/are-your-windows-forms-and-wpf-applications-ready-for-net-core-3-0/" target="_blank">released</a> 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 (<em>PortabilityReport.xlsx</em>) with several tabs:</p><p><strong>Portability Summary -</strong> 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.</p><p><strong>Details -</strong> 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.</p><p><strong>Missing assemblies -</strong> If your assemblies reference any other assemblies which could not be resolved by the tool, they will be listed here.</p><h3>My Thoughts</h3><p>I ran the tool on a large application with a mix of WinForms and WPF windows. The folder contains over 900 DLLs. My thoughts:</p><p>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.</p><p>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.</p><p>Third, many of the incompatible APIs are somewhat expected. Here are a few that came back in the report here:</p><ul><li>Microsoft.VisualBasic.* - If you have VB apps, and use APIs in this namespace, expect a lot of lines to appear in your report.</li><li>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.</li><li>Things that are less common in modern development like System.Xml.XmlDataDocument, System.Runtime.Remoting.Messaging, and System.Activator.GetObject.</li></ul><h3>Console Tool</h3><p>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 <a href="https://github.com/Microsoft/dotnet-apiport/releases/download/2.5.0-alpha/ApiPort.zip" target="_blank">here</a>, and instructions for using it are in the .NET team's post about the Portability Analyzer.</p><h3>Wrap-Up</h3><p>Go get your app ready for .NET Core 3.0 today! Your users will thank you later.</p><p><br></p><div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:93df89c4-5421-4d49-9b78-9a35b400a180" style="margin: 0px; padding: 0px; float: none; display: inline;">del.icio.us Tags: <a href="http://del.icio.us/popular/.net+core" rel="tag">.net core</a>,<a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/winforms" rel="tag">winforms</a>,<a href="http://del.icio.us/popular/uwp" rel="tag">uwp</a>,<a href="http://del.icio.us/popular/portability+analyzer" rel="tag">portability analyzer</a>,<a href="http://del.icio.us/popular/windows+10" rel="tag">windows 10</a>,<a href="http://del.icio.us/popular/desktop+packs" rel="tag">desktop packs</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-56212675627372943372018-05-29T08:24:00.001-04:002018-05-29T08:24:31.093-04:00TechBash 2018 Early Bird Tickets Now Available!<p>4-day (with Workshop) and 3-day early bird tickets are <a href="https://www.eventbrite.com/e/techbash-2018-tickets-45100931099" target="_blank">now on sale</a> 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 <a href="https://techbash.com/workshops" target="_blank">here</a>.</p><p>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 <a href="https://twitter.com/coolcsh" target="_blank">Scott Hunter</a>, leader of the Visual Studio and .NET Teams at Microsoft, and these other speakers have already been confirmed:</p><ul><li>Jeremy Likness</li><li>Jessica Deen</li><li>Richard Taylor</li><li>Jeremy Clark</li><li>Anna Bateman</li><li>Brendan Enrick</li><li>John Wright</li><li>Ashley Grant</li><li>Ivana Veliskova</li><li>Steve Bohlen</li><li>Angel Thomas</li><li>Jim Wooley</li><li>Walt Ritscher</li><li>Paul Hacker</li><li>Jeff Fritz</li><li>Mitch Denny</li><li>Anoop Kumar</li></ul><p>The full lineup will be announced soon. Get more info about TechBash <a href="https://techbash.com/" target="_blank">here</a> and <a href="https://www.eventbrite.com/e/techbash-2018-tickets-45100931099" target="_blank">buy your tickets today</a>!</p><p>See you this fall at the <a href="https://www.kalahariresorts.com/pennsylvania" target="_blank">Kalahari Resort in the Poconos</a>!</p><p><br></p><div class="wlWriterSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:031d6524-6b28-4352-a4c0-39d29116ca07" style="margin: 0px; padding: 0px; float: none; display: inline;">del.icio.us Tags: <a href="http://del.icio.us/popular/techbash" rel="tag">techbash</a>,<a href="http://del.icio.us/popular/kalahari+resort" rel="tag">kalahari resort</a>,<a href="http://del.icio.us/popular/docker" rel="tag">docker</a>,<a href="http://del.icio.us/popular/asp.net+core" rel="tag">asp.net core</a>,<a href="http://del.icio.us/popular/devops" rel="tag">devops</a>,<a href="http://del.icio.us/popular/microsoft+azure" rel="tag">microsoft azure</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-71614224695838578102017-11-30T09:10:00.001-05:002017-11-30T09:11:52.480-05:00WPF Tip #20 - Extended WPF Toolkit - IconButton ControlIt's time to explore a new control in the <a href="https://github.com/xceedsoftware/wpftoolkit">Extended WPF Toolkit</a>, maintained on GitHub by <a href="https://xceed.com/">Xceed</a> and the WPF community. Today, we will take a quick look at the <a href="https://github.com/xceedsoftware/wpftoolkit/wiki/IconButton" target="_blank">IconButton</a> control, which is new to v3.2.0 of the toolkit (<a href="https://github.com/xceedsoftware/wpftoolkit/releases/tag/3.2.0" target="_blank">released on Sept. 25th</a>).<br />
<br />
IconButton derives from a WPF Button and adds the ability to optionally place an Image to the left or right of your button's Content. There are a handful of properties available on top of the existing Button properties - Icon and IconBackground plus properties to change the button's appearance when users mouse over or press the button:<br />
<ul>
<li>MouseOverBackground</li>
<li>MouseOverForeground</li>
<li>MouseOverBorderBrush</li>
<li>MousePressedBackground</li>
<li>MousePressedForeground</li>
<li>MousePressedBorderBrush</li>
</ul>
These state-based properties are self-explanatory, so I created a brief example which uses only the Icon and IconLocation properties.<br />
<br />
<pre class="brush: xml"><xctk:IconButton Content="Launch Me" Padding="4"
HorizontalAlignment="Center" VerticalAlignment="Center"
IconLocation="Right">
<xctk:IconButton.Icon>
<Image Source="/WpfApp1;component/Images/Launchpad_Icon.png"
Width="16" Margin="4,0,0,0"/>
</xctk:IconButton.Icon>
</xctk:IconButton></pre>
<br />
<br />
The result is a window with a single "Launch Me" IconButton. There's an Apple-style launch icon to the right of the text set in the Content property. The image I used is a .png file in my project's Images folder set as a Resource. If you wanted to deploy the actual .png file, you would update the file to be "Content" and set the Image's Source property to <span style="font-family: "consolas";">"Images/Launchpad_Icon.png"</span>. This is the same practice you would use for any WPF image source.<br />
<br />
All of these properties can be set up via MVVM, data binding and code in your ViewModels to load the image and set its location at runtime based on other application configuration or user preferences.<br />
<br />
Here's is a look at the window at runtime:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcwXLSXgDyEMFZjPAUxAw9V8a-5dqdJrMoiNJdoAZL6vuYipk7sUlsWhHSBTE2wxt7-kUATESa7OcGQhKvp8CYtfela8Q9c8hlX3UumII73te9rwYf0LwtG6wrGjXW4U29DsrorHRnOXNo/s1600-h/wpf_xctk_iconbutton1%255B4%255D"><img alt="wpf_xctk_iconbutton1" border="0" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRJ5cAYnQEGPxTtJ_MQjWDDFbhgbjJ4HkEEoijTC2uFv2m7mNHNaXd9mt1BIgq7xPX8sCRs3JOUt0nTuH0GxvLWGuIrLb8ml5GMixR_A6dhP_REg252h82npBI6JAu2QpYRfwurT83zJLw/?imgmax=800" style="background-image: none; border: 0px currentcolor; display: inline;" title="wpf_xctk_iconbutton1" width="480" /></a><br />
<br />
It's a simple control that can save you a little bit of control templating. If this is something you could use in your project, the toolkit is free and available on NuGet.<br />
<br />
Happy coding!<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:746d5d25-960a-4a4b-af68-4bd8106a5cb2" style="display: inline; float: none; margin: 0px; padding: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com1tag:blogger.com,1999:blog-959852766553998174.post-26651750275260667272017-09-07T10:44:00.001-04:002017-09-07T10:47:00.258-04:00WPF Tip #19 - Extended WPF Toolkit - Zoom in with the Magnifier ControlIt's time to examine another control from the <a href="https://github.com/xceedsoftware/wpftoolkit" target="_blank">Extended WPF Toolkit</a>, maintained on GitHub by <a href="https://xceed.com/" target="_blank">Xceed</a> and the WPF community. Today, we will look at an example of how easy it is to add a zoom feature to your WPF application with the <a href="https://github.com/xceedsoftware/wpftoolkit/wiki/Magnifier" target="_blank">Magnifier control</a>.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSG7x9mK-iMcdmuvu4jMHWyXIiBwbYq9f0_Zxr8ZG6Z4cC_Sm-rcTdrgSHXdJzR9UNXxjK2oLWuhiJ8x79bWrVT2E_Dijt9q1SIiI464RQgCUukWQ6M8uQrXgCRP4abbU86fQotZqJff9P/s1600-h/Magnifier_magnifier_withborder%255B4%255D"><img alt="Magnifier_magnifier_withborder" border="0" height="267" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwaAglZWDU_YRl6vf-QMMW5gy2xbpYaYWHZ1VdYWMTb5TfRn6gSKNVN-fyiIAvnncnbONT_bi5A0FVSWVv_nHy2ZLcfhcULukdGsQl1RvAgNR8IY2GHfx8_wu_Vrty3dlQLUKAqLssR7uh/?imgmax=800" style="background-image: none; border: 0px; display: inline;" title="Magnifier_magnifier_withborder" width="400" /></a><br />
<br />
In the Xaml below, I have added a Magnifier to the top-level grid in my Window.<br />
<br />
<pre class="brush: xml"><Grid>
<tk:MagnifierManager.Magnifier>
<tk:Magnifier BorderBrush="MediumPurple"
BorderThickness="2"
Radius="80"
ZoomFactor=".4" />
</tk:MagnifierManager.Magnifier>
<tk:CheckListBox ItemsSource="{Binding Sentences, IsAsync=True}"
SelectedItem="{Binding SelectedSentence}"
Command="{Binding ItemSelectedCommand}"/>
</pre>
<br />
The CheckedListBox from <a href="http://www.wpf.tips/2017/08/wpf-tip-18-extended-wpf-toolkit-using.html" target="_blank">Tip #18</a> is still in place, displaying results from my Bacon Ipsum generator from <a href="http://www.wpf.tips/2017/08/wpf-tip-17-extended-wpf-toolkit.html" target="_blank">Tip #17</a>. Running the application, we see my random list items with a zoom region that follows my mouse as I move it around the Window.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1WylpPgsLRKMIIF6pJyK-N84sQpW1JHNL_9pfQWQp4rry5N2S65h6N4djp-bPp2gcmveYuu9r_6JK99caV96rF28hBEMAQrvpphGIrEwxZwaH9eJANZbG8T2undXPfBMSRgpu1295fuhc/s1600-h/zoom.bacon%255B4%255D"><img alt="zoom.bacon" border="0" height="513" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8XkUYtljI6cxOW4fc6k8pGQNXS3IwtdRWpTXIuo3bUEtpOTGNsJzBHH5YcXPx1rpSREjBEL8DXeTSlpS2NcN3xt583rLPjfbwjkBlrz33O5zc-4w0a_XQoafyktZgc7jkv62nFJ5jce_H/?imgmax=800" style="background-image: none; border: 0px; display: inline;" title="zoom.bacon" width="400" /></a><br />
<br />
Pretty simple! Go check it out for yourself. You can easily add a bound visibility property to hide/show the control from a toolbar or other button in your app.<br />
<br />
Happy coding!<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:2473ad1b-dd0c-4360-acaf-a122f26bcce3" style="display: inline; float: none; margin: 0px; padding: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/xaml" rel="tag">xaml</a>,<a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-88888560010241313232017-08-14T10:45:00.001-04:002017-08-14T10:47:37.490-04:00WPF Tip #18 - Extended WPF Toolkit - Using the CheckedListBox ControlIn today's tip, we're going to take a quick look at another control in the <a href="https://github.com/xceedsoftware/wpftoolkit">Extended WPF Toolkit</a>, the <a href="https://github.com/xceedsoftware/wpftoolkit/wiki/CheckListBox">CheckedListBox</a> control.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihJveBFk5YNECOLc6vuDopvbWuy91tLZ0ARNOXDHy7uxKd51mvgrwjEOhYBFdg4JoBEdEqk_NYKe8p9nmOfXkNTb2DO_VxedZwDiG2RxbGd9laYFNcW6-TdOA4xBx8dR-rkPWBo5qoj3aL/s1600-h/CheckListBox_wpf%255B3%255D"><img alt="CheckListBox_wpf" border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmNd-EotYjfyDxMtfuqmiElbhrmIChHITNDC8X5xTfykCcsFq5qORaOqwfTYJoIWGJzD9sbtBvor0MNGLjijaBBGwzjpKCqhmv1I0PW_dCHwAknGRGQ1BIsbJI2C6wyFU3pLCXi6f7KZVt/?imgmax=800" style="background-image: none; border: 0px; display: inline;" title="CheckListBox_wpf" width="222" /></a><br />
This control provides all of the functionality expected from a ListBox with the addition of checkboxes as a visual cue to indicate the selection state of each item.<br />
<br />
Using the control is quite simple. Here's an example of the XAML required to display a CheckedListBox on a WPF window. It is binding to the same collection of Sentence objects used in <a href="http://www.wpf.tips/2017/08/wpf-tip-17-extended-wpf-toolkit.html">Tip #17</a>.<br />
<br />
<pre class="brush: xml"><tk:CheckListBox ItemsSource="{Binding Sentences, IsAsync=True}"
SelectedItem="{Binding SelectedSentence}"
Command="{Binding ItemSelectedCommand}"/></pre>
<br />
ItemsSource binding to a collection to populate the list items. SelectedItem provides a way to find out the currently 'selected' item, the last item checked/unchecked. The Command will fire each time an item in the list is checked or unchecked, allowing ViewModel logic to act on this change.<br />
<br />
Go give it a try in your WPF project. Happy coding!<br />
<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:a8e8424b-b1c1-42b9-9fb5-580dd84709a6" style="display: inline; float: none; margin: 0px; padding: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/mvvm" rel="tag">mvvm</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com1tag:blogger.com,1999:blog-959852766553998174.post-41518632818094481962017-08-02T11:24:00.001-04:002017-08-02T11:30:00.949-04:00WPF Tip #17 - Extended WPF Toolkit - BusyIndicator ControlWelcome back to another <a href="https://github.com/xceedsoftware/wpftoolkit" target="_blank">Extended WPF Toolkit</a> sample. In this sample, we'll take a look at the <a href="https://github.com/xceedsoftware/wpftoolkit/wiki/BusyIndicator" target="_blank">BusyIndicator</a> control. This easy to use control provides a quick way to inform your users that a control or Window is currently being refreshed by a long-running process. This is a great way to both update your users of progress and keep them from interacting with the controls that are updating.<br />
Here is a fun little example that wraps a WPF DataGrid in a BusyIndicator. This is the entirety of the XAML inside the root Grid on the application's main window.<br />
<br />
<pre class="brush: xml"><tk:BusyIndicator IsBusy="{Binding IsGridLoading}" BusyContent="Loading, please wait..." DisplayAfter="0">
<DataGrid local:Commands.DataGridDoubleClickCommand="{Binding GridDoubleClickCommand}" ItemsSource="{Binding Sentences, IsAsync=True}"/>
</tk:BusyIndicator></pre>
<br />
The DataGridDoubleClickCommand is a work-around to make the DataGrid's MouseDoubleClick event work with ICommand in when data binding in MVVM. More info <a href="https://social.msdn.microsoft.com/Forums/vstudio/en-US/632ea875-a5b8-4d47-85b3-b30f28e0b827/mousedouble-click-or-singleclick-on-datagrid-in-mvvm-how-can-i-do-that?forum=wpf" target="_blank">here</a>.<br />
<br />
In the MainViewModel, there is an IsGridLoading boolean property that will be used to toggle the BusyIndicator on/off. The GridDoubleClickCommand invokes OnGridDoubleClicked() when the user double-clicks somewhere on the DataGrid at runtime. In this method, we're clearing and repopulating the Sentences ObservableCollection to which our DataGrid is bound. Notice the use of async/await. This is necessary to make the BusyIndicator appear. Without this, the UI will freeze during the update and never show the BusyIndicator control.<br />
<br />
<pre class="brush: csharp">private async void OnGridDoubleClicked()
{
//set the IsBusy before you start the thread
IsGridLoading = true;
RaisePropertyChanged(nameof(IsGridLoading));
//no direct interaction with the UI is allowed from this method
lock (_sentenceLock)
{
Sentences.Clear();
}
await BuildSentenceList(5, 15, 25, 50);
//work has completed. you can now interact with the UI
IsGridLoading = false;
RaisePropertyChanged(nameof(IsGridLoading));
}</pre>
<br />
The _sentenceLock allows us to update our ObservableCollection on a background thread. You must also initialize the collection with this code in your constructor. This tells WPF to update the collection on the UI thread and which lock object to use. More info <a href="https://msdn.microsoft.com/en-us/library/hh140164(v=vs.110).aspx" target="_blank">here</a>.<br />
<br />
<pre class="brush: csharp">BindingOperations.EnableCollectionSynchronization(Sentences, _sentenceLock);</pre>
<br />
Each row in the DataGrid will be populated with some random <a href="http://baconipsum.com/" target="_blank">Bacon Ipsum</a> data in the BuildSentenceList method. There is an API if you would like to remove the hard-coded array of words.<br />
<br />
<pre class="brush: csharp">private async Task BuildSentenceList(int minWords, int maxWords,
int minSentences, int maxSentences)
{
var words = new[]{"bacon", "ipsum", "dolor", "tail", "amet", "swine",
"chicken", "short", "loin", "jowl", "turkey", "ball", "tip",
"beef", "shank", "rump", "t-bone", "ham", "porchetta", "filet",
"pork", "jerky", "hock", "meatball", "biltong", "steak", "brisket"};
var rand = new Random();
int numSentences = rand.Next(maxSentences - minSentences)
+ minSentences + 1;
int numWords = rand.Next(maxWords - minWords) + minWords + 1;
var result = new StringBuilder();
Task t = Task.Run(() =>
{
for (int s = 0; s < numSentences; s++)
{
for (int w = 0; w < numWords; w++)
{
if (w > 0)
{
result.Append(" ");
}
result.Append(words[rand.Next(words.Length)]);
}
result.Append(". ");
lock (_sentenceLock)
Sentences.Add(new Sentence() {SentenceContent = result.ToString()});
Thread.Sleep(100);
result.Clear();
}
});
await t;
}</pre>
<br />
When the code to populate the grid fires, thanks to the 100ms Thread.Sleep between each row generated, you can see the grid slowly populating with data behind the busy indicator.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiINLierXl1Z8oyVVgPJQsi2yut_uWYQf2lSlECKYc7rk4MDddrnrQ5MmKVhCTe3Xm5dkTsLVVZ7O4oGc-gsw0a40L0DaW1GEuX0UGAyRtyGU8aYJi0HXmcfN0-jp_3_HqzXf1HA-vSAD_k/s1600-h/baconipsum-loading%255B4%255D"><img alt="baconipsum-loading" border="0" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdAN2bE-xn-OAwsOIPTwI6Z2oQDE6QOtGrrfli61KliSApT64Bj0birVU4KaA80wQvqmNz8xzK2WbKuWoEjFdAZXhop0dOaQTw_JfxCATzH_n-W7Eu_42niCzMZf-WL0Sg2QUSGi0-VPWd/?imgmax=800" style="background-image: none; border: 0px; display: inline;" title="baconipsum-loading" width="480" /></a><br />
<br />
It's a great control. Just remember to update your data on a background thread!<br />
<em><br /></em>
<em>Happy coding!</em><br />
<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:b8ffec18-71a5-4a48-a46f-2376e96d5f5a" style="display: inline; float: none; margin: 0px; padding: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/mvvm" rel="tag">mvvm</a>,<a href="http://del.icio.us/popular/async" rel="tag">async</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-7146300274364022852017-07-25T08:21:00.001-04:002017-07-25T08:26:16.724-04:00WPF Tip #16 - Extended WPF Toolkit - ChildWindow & MessageBox ControlsWelcome to another <a href="https://github.com/xceedsoftware/wpftoolkit" target="_blank">Extended WPF Toolkit</a> tip. In this tip, we will look at a couple of simple uses of the <a href="https://github.com/xceedsoftware/wpftoolkit/wiki/ChildWindow" target="_blank">ChildWindow</a> and <a href="https://github.com/xceedsoftware/wpftoolkit/wiki/MessageBox" target="_blank">MessageBox</a> controls.<br />
<br />
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.<br />
<br />
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.<br />
<br />
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:<br />
<br />
<pre class="brush: xml"><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></pre>
<br />
The MessageBox's button has a Click event handler to display the control:<br />
<br />
<pre class="brush: csharp">private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
SampleMsgBox.ShowMessageBox();
}</pre>
<br />
The two ChildWindows are opened with Commands attached to the first two buttons in our Window's ViewModel:<br />
<br />
<pre class="brush: csharp">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; }</pre>
<br />
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.<br />
<br />
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.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl_hnbG2nPvC81WAuvifCLZgQ8OnuLyLjJ9am1jhmZxOijSebuiPkhxLEjdxdzYCb30p6MoubjmZKJED9qwagXIqIorL2ktJTaH38SVDeY1_iDHYu_-_28P7T29HT6IEdxSyfL1Vyesl5W/s1600-h/childwindows-wpf%255B6%255D"><img alt="childwindows-wpf" border="0" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6W6-4TvVd2pLbdY3EPNiuMrHzHqT9bd_1y1wCyrZZpJfzWJSPiJfhgiweL-zPRa0DicTgh49lHvWVjU-Cy0rpUPiScfXWC1f8RFydTOsaRVhDkW1mPmswgk-IBhXE8D-6OiKKshjIZbYG/?imgmax=800" style="background-image: none; display: inline;" title="childwindows-wpf" width="484" /></a><br />
<br />
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 <a href="https://github.com/xceedsoftware/wpftoolkit" target="_blank">download the toolkit today</a>.<br />
<br />
Happy coding!<br />
<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:752d09e6-bcb9-4225-bf13-dea7f5580608" style="display: inline; float: none; margin: 0px; padding: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/mvvm" rel="tag">mvvm</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-16321872076645803602017-07-18T08:00:00.001-04:002017-07-18T08:00:31.022-04:00WPF Tips Update - The Extended WPF Toolkit Has a New Home<p>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.</p><p>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.</p><h3><a href="https://github.com/xceedsoftware/wpftoolkit" target="_blank">Download, Star and Watch the Extended WPF Toolkit on GitHub</a></h3><p align="left">The <a href="https://github.com/xceedsoftware/wpftoolkit/wiki/Improvements-in-v3.1.0" target="_blank">changelog</a> for v3.1.0 includes 37 fixes and enhancements. The <a href="https://github.com/xceedsoftware/wpftoolkit/wiki/Xceed-Toolkit-Plus-for-WPF" target="_blank">Plus Edition</a> 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.</p><p align="left"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-7Jd54ODgUit0wBvsv06f96ExB5QqKjNcWiP3JNb9rlpmlNuOpNcDydtQVGynWd_F2kLERc4Y7dDvdxs-NP8e8J7BXSRd7mwc1k_BIu75Zs2xoMxr2pndoYnzak0Uk1vUrdP0cQBT8C5A/s1600-h/wpftoolkit-github%255B7%255D"><img width="480" height="232" title="wpftoolkit-github" style="border: 0px currentcolor; border-image: none; display: inline; background-image: none;" alt="wpftoolkit-github" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqZSb2wXMZYmVOLs7KPER7rihW4RUeXOq_H9QuJe0g48wvC9CjKUicJEV3KsroxBiwLc_lpYgnWVju9XMgJptn-hKJqV-YvpOl25Ghb8CbkzTZWqJfe07SJsjxbpfzV0iQs2p2lcmmdYTb/?imgmax=800" border="0"></a></p><p align="left">Learn all about the toolkit on GitHub or check out <a href="http://www.wpf.tips/2017/06/wpf-tip-11-free-controls-with-extended.html" target="_blank">WPF Tip #11</a>. 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!</p><p align="left">Happy coding!</p><p align="left"><br></p><div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:2cf6f54d-f722-487f-9f70-8e77558cec9c" style="margin: 0px; padding: 0px; float: none; display: inline;">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/xceed" rel="tag">xceed</a>,<a href="http://del.icio.us/popular/github" rel="tag">github</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-69203756148745410282017-07-08T12:42:00.004-04:002017-07-08T12:42:50.529-04:00WPF Tip #15 - Extended WPF Toolkit - The DataGrid Control<a href="https://www.blogger.com/$wpfgrid2[4].png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="https://www.blogger.com/$wpfgrids1[5].png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a>Tip #15 is a quick detour. We'll get back to using the CalculatorUpDown control in Tip #16.<br />
<br />
If you are looking for a quick, free way to upgrade your application's DataGrid look and behavior, the <a href="https://wpftoolkit.codeplex.com/" target="_blank">Extended WPF Toolkit</a> includes a <a href="https://wpftoolkit.codeplex.com/wikipage?title=DataGrid&referringTitle=Home" target="_blank">DataGrid</a> which provides a significant upgrade over the WPF DataGrid in the .NET Framework.<br />
<br />
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.<br />
<blockquote>
<span style="font-family: Consolas;"><Grid><br /> <Grid.RowDefinitions><br /> <RowDefinition Height="*"/><br /> <RowDefinition Height="*"/><br /> </Grid.RowDefinitions><br /> <br /> <DataGrid ItemsSource="{Binding Path=MediaCatalog, IsAsync=True}"/></span><br />
<span style="font-family: Consolas;"> <xcdg:DataGridControl Grid.Row="1" ItemsSource="{Binding Path=MediaCatalog, IsAsync=True}"/></span><br />
<span style="font-family: Consolas;"></Grid></span></blockquote>
This is what we get when running the application.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCjBp2cArbeT6BBpyqCovI3XrPYVdCP_w0UjKGNelQL8j6mcgbPB4u5fw04uz_ZaoPO2Sd1ymlX8mmLOqh7VhpFzv0tAGYmOVa1pnxeP1MBM1eA8ngVG5a7yvAk8lekouXLLuFB1M4Z3Kd/s1600/wpfgrids1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="470" data-original-width="784" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCjBp2cArbeT6BBpyqCovI3XrPYVdCP_w0UjKGNelQL8j6mcgbPB4u5fw04uz_ZaoPO2Sd1ymlX8mmLOqh7VhpFzv0tAGYmOVa1pnxeP1MBM1eA8ngVG5a7yvAk8lekouXLLuFB1M4Z3Kd/s400/wpfgrids1.png" width="400" /></a></div>
<br />
<br />
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.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPXTRMUPCjQz95ZbkrswJKyOK6ypo4HGSEjkUEn6jWeYLlUmmPpIaMeZNJKq9WJ8mjY_BTkivd6gMk4FcVVviJQF6OD4A0lU4PTtyddRIq7jg9HmuxsVv6mCvPqbGv3SzOiaO7z2lGjE3G/s1600/wpfgrid2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="312" data-original-width="434" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPXTRMUPCjQz95ZbkrswJKyOK6ypo4HGSEjkUEn6jWeYLlUmmPpIaMeZNJKq9WJ8mjY_BTkivd6gMk4FcVVviJQF6OD4A0lU4PTtyddRIq7jg9HmuxsVv6mCvPqbGv3SzOiaO7z2lGjE3G/s320/wpfgrid2.png" width="320" /></a></div>
<br />
<br />
For more information about features available in the control, go check out the <a href="https://wpftoolkit.codeplex.com/" target="_blank">CodePlex site</a> (migrating soon).<br />
<br />
Happy Coding!<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:b7c44985-7b9e-4952-8e48-98a4222ddae9" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/data+binding" rel="tag">data binding</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-35659992855756093052017-06-23T08:01:00.001-04:002017-07-24T14:24:05.723-04:00WPF Tip #14 - Extended WPF Toolkit - The CalculatorUpDown ControlIn this tip, we will continue to explore the free controls available in the <a href="https://wpftoolkit.codeplex.com/" target="_blank">Extended WPF Toolkit Community Edition</a>.<br />
<br />
The <a href="https://wpftoolkit.codeplex.com/wikipage?title=CalculatorUpDown" target="_blank">CalculatorUpDown</a> control is a hybrid of sorts. It takes the functionality of an up/down numeric control and adds a dropdown button. Clicking on the dropdown button pops open a Calculator control. The output of the calculator displays in its window as well as in the text portion of the CalculatorUpDown.<br />
<br />
Let's take a simple example of the control's use and walk through a few of the properties and how they impact the control's functionality. Here is the XAML:<br />
<blockquote>
<span style="font-family: Consolas;"><tk:CalculatorUpDown Grid.Row="1" Height="32" VerticalAlignment="Top" FormatString="C2" Watermark="Calculate!" Increment=".01" Maximum="9999.99" Minimum="0.01"/></span></blockquote>
Upon first launching the window, this is how the control looks:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTlXKBLoU1xc5gr0_eZWOAAR7ZT8vZ7HfuqnQuYzwp6ZjrE7gFcBCl1iZ4nRnyU5rCEvFgmg8mbfgClxd2cOaUOfuirtJ6jrBNNmZ3VSXgHg-HUqVPJ4tCF8xctRk_m8Zj-_6VjuU4buuB/s1600-h/calc0%255B6%255D"><img alt="calc0" border="0" height="46" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWRYhS_RLdjkz2_SzYXWLLT8ajmAVhT2YPDF_Rsdjs-etdeGWctkrkBYPrQDdXPK802PPW8gbd1D2fBshaSY4xDZCLX8glPz430PNbJLrUXQnBtCOGOWeHJpoxs4M8RpirYNGiTR5vwuqn/?imgmax=800" style="background-image: none; border: 0px; display: inline;" title="calc0" width="480" /></a><br />
There is a numeric up/down with a watermark reading "Calculate!" and a dropdown button to open the calculator control. Let's click the up button to start.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ6GUxa7FaoNYWdfpPwKT6h_NvzsHryuamf4-mVGBu1HdpAtdbPA7pmbm4oHW6iLMd0MFQ6trKiDTm-CVX0YCKduj67QJtMBTBfr9mllkThbDz3fMDiSh_F66YYwmaNi-AwYsRu8j5XO7l/s1600-h/calc0a%255B4%255D"><img alt="calc0a" border="0" height="50" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyAiTbabdihWOizAGw_RK-QmbQFS96wTsEZ4Gdv9aw_YKPtz9e4PQG0sYsXtUAgx81oF1yMVdVQLt-q_-S_97Gp7ggAcstwbPtFpSZM65_izO-H9vDsuSaep9qPMS-_dA7wKaeyNAUHJih/?imgmax=800" style="background-image: none; border: 0px; display: inline;" title="calc0a" width="480" /></a><br />
The Increment property is set to ".01" and the FormatString is "C2", so our value has incremented to $0.01 or 1 U.S. cent. You'll notice that the down button is now disabled because the Minimum property is currently equal to the control's Value.<br />
<br />
Now to explore the calculator control a little. Click the dropdown button and enter a calculation.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYssBwajEn6pNMm7o7O6UAO2Gx4xy7z3UfMUN9RirvnEqx5VatlytLKNsR0P7P_E_resYCyCfBpmfQHnixVirWaXHyc-YBsXLF1pMStYJnqPHsYHI9Wxbfjlxys3dmhLFNsPhms5hX8W-r/s1600-h/calc1%255B4%255D"><img alt="calc1" border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvvNQiKz8gB5B1M0kzsaOYHe4DXGgyuef_Dvw5kDw9tjQCJkcyvujDnips1_F3UP0OI7ibL_5i7moW23N7GZR3O2iu9wuulTOZaYdf0G-X-5XX0pMQDIyBy9kFs62HM8hIkjternGzczh4/?imgmax=800" style="background-image: none; border: 0px; display: inline;" title="calc1" width="480" /></a><br />
As you use the calculator, you will notice that the calculator window updates as you enter and calculate values, but the textbox of the control only updates to show results of calculations. If the calculated value falls outside the Maximum or Minimum properties, it will default to those Max/Min values.<br />
<br />
There was no code required on our part to add this rich functionality or our application, only the XAML markup seen above. You certainly could take this a step further by adding some data binding and leveraging other properties that the control exposes to do things like allowing the user to change the number format.<br />
<br />
Happy coding!<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:1e00eaa0-fc58-4693-980c-970394463c8d" style="display: inline; float: none; margin: 0px; padding: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/xaml" rel="tag">xaml</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-38427964286283069062017-06-13T08:31:00.001-04:002017-06-13T08:31:58.218-04:00WPF Tip #13 - Extended WPF Toolkit - ColorCanvas with MVVMLight, Binding and EventToCommand<p>In <a href="http://www.wpf.tips/2017/06/wpf-tip-12-extended-wpf-toolkit.html" target="_blank">Tip #12</a>, we used a ColorCanvas control in a SplitButton to change the Background color of the SplitButton using an event in the code behind. In this tip, we will do the same thing with data binding and commands using <a href="http://www.mvvmlight.net/" target="_blank">MVVMLight</a>.</p><p>The first step is to add the MVVMLight NuGet package to the project:</p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGXzneuoimGAq3TjLrvtOrTDPcIQDj3AgfAQO6SbhJHHEdQ3uNo7UtMNrn7rhKcdojx79MDYg1RpR48OPft-WWg4tCJljkRP0DcBOFutD7eBJvU7-c2Jx_5nZud9Tdneihv8xj3SaUuN4e/s1600-h/image%255B5%255D"><img width="540" height="51" title="image" style="border: 0px currentcolor; border-image: none; display: inline; background-image: none;" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRpRZErledZK62Cf99HJ6YZ6rj-s_lw2CcpDzy9DvP3Ei5gjmVXmA6kw2oaW6GR4aggiZ4bnhbH6vKtg-f9rM14ER2OwgPJP5amk9OEJn6bpk_JyknRlF32r80LwQOw9Ooej8qdGIKQXrN/?imgmax=800" border="0"></a></p><p>Adding the package will add and update several classes in the project. We now have a MainViewModel and ViewModelLocator inside a ViewModel folder. The locator class exposes each ViewModel in the project so they can be bound in your views. To make the locator discoverable to the views in the project, MVVMLight added a new resource to the App.xaml:</p><blockquote><p><font face="Consolas"><Application.Resources><br> <ResourceDictionary><br> <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:WpfApp1.ViewModel" /><br> </ResourceDictionary><br>
</Application.Resources></font><br>
</p></blockquote><p>Now lets start with the changes we have to make. First remove the event handler from the MainWindow.xaml.cs. The next step is to replace that functionality with some decoupled logic in the MainViewModel. Two things are needed:</p><ul><li>A ButtonBrush property to bind the SplitButton's Background property.</li><li>A ChangeBrushColorCommand RelayCommand to bind to the ColorChanged event of the ColorCanvas.</li></ul><p>An OnColorChanged method is added to do the work needed when the RelayCommand is invoked. These are hooked up in the constructor, along with some default colors for the SplitButton. I made the button different colors at design-time and runtime as a way to validate that my binding code isn't broken. Here's the complete MainViewModel implementation:</p><blockquote><p><font face="Consolas">public class MainViewModel : ViewModelBase<br>
{<br> public MainViewModel()<br> {<br> if (IsInDesignMode)<br> {<br> ButtonBrush = new SolidColorBrush(Colors.LightGray);<br> }<br> else<br> {<br> ButtonBrush = new SolidColorBrush(Colors.LightSkyBlue);</font></p><font face="Consolas">
</font><p><font face="Consolas"> ChangeBrushColorCommand = new RelayCommand<Color?>(OnColorChanged);<br> }<br> }</font></p><font face="Consolas">
</font><p><font face="Consolas"> public SolidColorBrush ButtonBrush { get; set; }</font></p><font face="Consolas">
</font><p><font face="Consolas"> internal void OnColorChanged(Color? p_Param)<br> {<br> if (p_Param.HasValue)<br> {<br> ButtonBrush = new SolidColorBrush(p_Param.Value);<br> }<br> else<br> {<br> ButtonBrush = new SolidColorBrush(Colors.Transparent);<br> }</font></p><font face="Consolas">
</font><p><font face="Consolas"> RaisePropertyChanged(nameof(ButtonBrush));<br> }</font></p><font face="Consolas">
</font><p><font face="Consolas"> public RelayCommand<Color?> ChangeBrushColorCommand { get; private set; }<br>
}</font><br>
</p></blockquote><p>The next thing we need is a converter class to convert the event args of the ColorChanged event to the Color? parameter type of our RelayCommand. SelectedColorChangedToColorConverter implements the IEventArgsConverter in MvvmLight. It's similar to value converters you may have created for data binding in WPF (<a href="http://www.wpf.tips/2017/03/wpf-tip-4-data-binding-with.html" target="_blank">see WPF Tip #4</a>).</p><blockquote><p><font face="Consolas">public class SelectedColorChangedToColorConverter : IEventArgsConverter<br>
{<br> public object Convert(object value, object parameter)<br> {<br> var args = (RoutedPropertyChangedEventArgs<Color?>)value;</font></p><font face="Consolas">
</font><p><font face="Consolas"> return args.NewValue ?? Colors.Transparent;<br> }<br>
}</font><br>
</p></blockquote><p>Finally, lets make a few changes to the MainWindow view.</p><p>Set the DataContext for the Window using the ViewModelLocator:</p><blockquote><p><font face="Consolas">DataContext="{Binding Main, Source={StaticResource Locator}}"</font></p></blockquote><p>Add the converter to the Window.Resources:</p><blockquote><p><font face="Consolas"><Window.Resources><br> <ResourceDictionary><br> <local:SelectedColorChangedToColorConverter x:Key="SelectedColorChangedToColorConverter" /><br> </ResourceDictionary><br>
</Window.Resources></font><br>
</p></blockquote><p>Update the SplitButton to bind its Background property and the ColorCanvas to use the MVVMLight EventToCommand trigger, hooking up our RelayCommand through the converter.</p><blockquote><p><font face="Consolas"><tk:SplitButton Content="Pick a Color" Height="32" Width="120" Background="{Binding ButtonBrush}"><br> <tk:SplitButton.DropDownContent><br> <tk:ColorCanvas x:Name="MainColorCanvas"><br> <i:Interaction.Triggers><br> <i:EventTrigger EventName="SelectedColorChanged"><br> <command:EventToCommand Command="{Binding ChangeBrushColorCommand, Mode=OneWay}"<br> EventArgsConverter="{StaticResource SelectedColorChangedToColorConverter}"<br> PassEventArgsToCommand="True"/><br> </i:EventTrigger><br> </i:Interaction.Triggers><br> </tk:ColorCanvas><br> </tk:SplitButton.DropDownContent><br>
</tk:SplitButton></font><br>
</p></blockquote><p>That's it!. Same functionality, but now with better separation between view and code.</p><p>Happy coding! (P.S. - I hope to get some proper code formatting hooked up to Blogger soon… or maybe a new blogging platform. Thanks for bearing with me.)</p><p><br></p><div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:843f261f-56a9-4213-822d-d0f62b2b6172" style="margin: 0px; padding: 0px; float: none; display: inline;">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/mvvm+light" rel="tag">mvvm light</a>,<a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/eventtocommand" rel="tag">eventtocommand</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-54304454257642762102017-06-07T08:45:00.001-04:002017-06-07T08:45:31.788-04:00WPF Tip #12 - Extended WPF Toolkit - ColorCanvas<p>Last time in <a href="http://www.wpf.tips/2017/06/wpf-tip-11-free-controls-with-extended.html" target="_blank">Tip #11</a>, I explained the Extended WPF Toolkit and the different versions that are available. In the quick-n-dirty example, I added a SplitButton with a <a href="http://wpftoolkit.codeplex.com/wikipage?title=ColorCanvas&referringTitle=Home" target="_blank">ColorCanvas</a> that displays when opening the dropdown portion of the buttom.</p><p>In this tip, we are going to add just a few lines of code to take the color selected in the ColorCanvas and apply it as the background color of the SplitButton.</p><p>Let's start with the Xaml. There are two changes needed here (<font style="background-color: rgb(255, 255, 0);">highlighted</font> below). The first is to name the button so it can be referenced from the application's code. The second is adding a handler to the ColorCanvas' SelectedColorChanged event. This event fires every time the color changes on the canvas and provides the OldValue and NewValue as parameters in the event.</p><blockquote><p><font face="Consolas" size="1"><tk:SplitButton <font style="background-color: rgb(255, 255, 0);">x:Name="mainSplitButton"</font> Content="Pick a Color" Height="32" Width="120"><br> <tk:SplitButton.DropDownContent><br> <tk:ColorCanvas <font style="background-color: rgb(255, 255, 0);">SelectedColorChanged="ColorCanvas_OnSelectedColorChanged"</font> /><br> </tk:SplitButton.DropDownContent><br>
</tk:SplitButton></font></p></blockquote><p>In the code behind for the Window, I have added the ColorCanvas_OnSelectedColorChanged event handler with some code to set the SplitButton's background color to a new SolidColorBrush the color of the NewValue selected on the ColorCanvas, provided it's not null.</p><blockquote><p><font face="Consolas" size="1">private void ColorCanvas_OnSelectedColorChanged(object sender, RoutedPropertyChangedEventArgs<Color?> e)<br>
{<br> if (e.NewValue.HasValue)<br> {<br> mainSplitButton.Background = new SolidColorBrush(e.NewValue.Value);<br> }<br>
}</font></p></blockquote><p>You could add an else condition to handle nulls by setting the background color back to some default color. Here's what the end result looks like.</p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgj_YRGFGtFJqYKYvKHPsInTGp2OMIjv0zb-9F4eWOo9xn-3UpFjOwheQcMFeYxY8WGwaGhsZOnMSAWMV96YWaNYZ_T11xyRt0WOzwwHKGg38wpretVdy0jWqEWUO12hKsnxJbReTaWMj6n/s1600-h/colorcanvas%255B4%255D"><img width="400" height="373" title="colorcanvas" style="border: 0px currentcolor; border-image: none; display: inline; background-image: none;" alt="colorcanvas" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieULIkvVfRIc1EWstBlrHxAA0dFvuI9jIgyZCSyEifqpqZy97GG-OwnQkXxF6B3Z-OviKErsP8vk5PiRR3aCIfMGneKN01oPvhrILay7sgOOKzD3EkBWBWXeO_JGX_9xch95ISEp8RcoFa/?imgmax=800" border="0"></a></p><p>If you were following the MVVM pattern in your application, you would handle this through data binding and commands. In Tip #13, we will add MVVMLight to the mix and rework the example to follow this pattern.</p><p><br>
</p><p><div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:4d84ce65-4696-4a08-b442-924ea6ae3f18" style="margin: 0px; padding: 0px; float: none; display: inline;">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/extended+wpf+toolkit" rel="tag">extended wpf toolkit</a>,<a href="http://del.icio.us/popular/xaml" rel="tag">xaml</a></div></p>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-86975255169455866602017-06-01T09:20:00.001-04:002017-06-01T10:08:22.074-04:00WPF Tip #11 - Free Controls with the Extended WPF Toolkit Community EditionEveryone loves free things. When it comes to WPF controls, there is a wide selection of 3rd party components from which to choose: Telerik, Infragistics, DevExpress, etc. If you're an independent developer or a small business on a tight budget, the Extended WPF Toolkit, maintained by Xceed, is a great choice.<br />
<br />
<a href="https://wpftoolkit.codeplex.com/" target="_blank">Currently available on Codeplex</a>, the Community Edition of the toolkit includes nearly 50 WPF controls. These are just a few:<br />
<ul>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=CheckListBox&referringTitle=Home" target="_blank">CheckListBox</a></li>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=ColorPicker&referringTitle=Home" target="_blank">ColorPicker</a></li>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=DataGrid&referringTitle=Home" target="_blank">DataGrid</a></li>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=DateTimePicker&referringTitle=Home" target="_blank">DateTimePicker</a></li>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=DropDownButton&referringTitle=Home" target="_blank">DropDownButton</a></li>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox&referringTitle=Home" target="_blank">MaskedTextBox</a></li>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=RichTextBox&referringTitle=Home" target="_blank">RichTextBox</a></li>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=WatermarkTextBox&referringTitle=Home" target="_blank">WatermarkTextBox</a></li>
<li><a href="https://wpftoolkit.codeplex.com/wikipage?title=Wizard&referringTitle=Home" target="_blank">Wizard</a></li>
</ul>
Xceed also offers two paid versions of the toolkit with additional controls and technical support, the <a href="https://wpftoolkit.codeplex.com/wikipage?title=Compare%20Editions" target="_blank">Plus Edition</a> and the <a href="https://xceed.com/xceed-business-suite-for-wpf/" target="_blank">Business Suite for WPF</a>.<br />
<br />
The latest release of the community edition is 3.0.0 and was released in Dec. 2016. I have recently contacted Xceed to inquire about their plans for the future of the toolkit and whether it will be migrated to GitHub or another host. As you may be aware, Codeplex is shutting down this year. See <a href="https://aka.ms/codeplex-announcement" target="_blank">Brian Harry's post</a> about the transition to GitHub for Codeplex projects.<br />
<br />
<b>EDIT: A representative replied to me to inform me that there will be an announcement about the migration of the Extended WPF Toolkit from Codeplex within a month.</b><br />
<br />
In the spirit of including some code in these tips, here is a quick sample of the little bit of code required to add a SplitButton that opens a ColorPicker control for the user:<br />
<blockquote>
<span style="font-family: Consolas; font-size: xx-small;"><Window x:Class="WpfApp1.MainWindow"<br /> xmlns="</span><a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation%22"><span style="font-family: Consolas; font-size: xx-small;">http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span></a><br /><span style="font-family: Consolas; font-size: xx-small;"> xmlns:x="</span><a href="http://schemas.microsoft.com/winfx/2006/xaml%22"><span style="font-family: Consolas; font-size: xx-small;">http://schemas.microsoft.com/winfx/2006/xaml"</span></a><br /><span style="font-family: Consolas; font-size: xx-small;"> xmlns:d="</span><a href="http://schemas.microsoft.com/expression/blend/2008%22"><span style="font-family: Consolas; font-size: xx-small;">http://schemas.microsoft.com/expression/blend/2008"</span></a><br /><span style="font-family: Consolas; font-size: xx-small;"> xmlns:mc="</span><a href="http://schemas.openxmlformats.org/markup-compatibility/2006%22"><span style="font-family: Consolas; font-size: xx-small;">http://schemas.openxmlformats.org/markup-compatibility/2006"</span></a><br /><span style="font-family: Consolas; font-size: xx-small;"> xmlns:local="clr-namespace:WpfApp1"<br /> xmlns:tk="</span><a href="http://schemas.xceed.com/wpf/xaml/toolkit%22"><span style="font-family: Consolas; font-size: xx-small;">http://schemas.xceed.com/wpf/xaml/toolkit"</span></a><br /><span style="font-family: Consolas; font-size: xx-small;"> mc:Ignorable="d"<br /> Title="MainWindow" Height="350" Width="525"><br /> <Grid><br /> <tk:SplitButton Content="Pick a Color" Height="32" Width="120"><br /> <tk:SplitButton.DropDownContent><br /> <tk:ColorCanvas /><br /> </tk:SplitButton.DropDownContent><br /> </tk:SplitButton><br /> </Grid><br />
</Window></span></blockquote>
The end result when running the app looks like this with the button open:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2SWo2RO2CLB5aNW_k0uGClXA1_xfj9eNNaznTabsUA-ZssFrah2XXeyuVXiGYpym_rHMn6DY7C173e0U6EoxZGbZcPxQe4DSSE7uXj3PvtzpAmzimwiWpEXeCsc78urGCJXCArQJEP7Hy/s1600-h/image%255B2%255D"><img alt="image" border="0" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtNaaUAkSfxSbKbwZa5S0na8hnBAPgTI_FGS73nL9NEML7-j3_qkigFGA6S7kU26BBG2EPmAfRL8oxd85ujTsH0_IHxlrdbxDilOkOcoua3D573GShbzL9THYaLJXXGltCs7pVWwDjt6CO/?imgmax=800" style="background-image: none; display: inline; margin: 0px;" title="image" width="244" /></a><br />
The color picker itself require a little more code to setup. Let's take a look at its use in our next tip.<br />
<br />
Happy coding!<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:9d929c04-2634-4e7f-9ebe-65525fb1cb08" style="display: inline; float: none; margin: 0px; padding: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/xceed" rel="tag">xceed</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-60758868373968022652017-05-16T09:11:00.001-04:002017-05-16T09:11:01.705-04:00WPF Tip #10 - Update ObservableCollection From a Background Thread<p>Pete Brown has a detailed blog post about updating <a href="https://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx" target="_blank">ObservableCollection</a> from background threads. I wanted to share the link to <a href="http://10rem.net/blog/2012/01/16/wpf-45-observable-collection-cross-thread-change-notification" target="_blank">his post from 2012</a> and share a quick code snippet that illustrates how to do this in .NET 4.5 and later.</p> <p>Before .NET 4.5, background updates to an ObservableCollection had to dispatch calls to the UI thread. Now all that is required is making a single call after initializing the collection in your ViewModel or other .NET class:</p> <blockquote> <p><font size="2" face="Consolas">public ObservableCollection<MyObservableType> MyObservableCollection { get; set; }<br> <br>private object _myCollectionLock = new object();<br> <br>public MainViewModel()<br>{<br> MyObservableCollection = new ObservableCollection<MyObservableType>();<br> <br> <font style="background-color: #ffff00">BindingOperations.EnableCollectionSynchronization(MyObservableCollection, _myCollectionLock);</font><br>}</font></p></blockquote> <p>Go check out <a href="http://10rem.net/blog/2012/01/16/wpf-45-observable-collection-cross-thread-change-notification" target="_blank">Pete's post with the full details</a>.</p> <p>Cheers!</p> <div id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:acd2151f-1222-4f44-af64-282a657eeb65" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/mvvm" rel="tag">mvvm</a>,<a href="http://del.icio.us/popular/threading" rel="tag">threading</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-45159804226638809092017-04-26T15:49:00.001-04:002017-04-26T15:49:01.144-04:00WPF Tip #9 - ObservableCollection and the CollectionChanged Event<p>Tip #9 will examine something that seems like it should work according to the documentation on MSDN, but I have seen it not work as expected.</p> <p>When using <a href="https://msdn.microsoft.com/en-us/library/ms668604%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396" target="_blank">ObservableCollection<T></a>, if some code in your application needs to react when items are added or removed from the collection the <a href="https://msdn.microsoft.com/en-us/library/ms653375(v=vs.110).aspx" target="_blank">CollectionChanged</a> event can be handled.</p> <blockquote> <p><font size="2" face="Consolas">private ObservableCollection<Pill> _pills = new ObservableCollection<Pill>();</font></p> <p><font size="2" face="Consolas">public MainWindow()<br>{<br> InitializeComponent();<br> Pills.CollectionChanged += Pills_CollectionChanged;<br>}</font></p> <p><font size="2" face="Consolas">public ObservableCollection<Pill> Pills<br>{<br> get { return _pills; }<br> set { _pills = value; }<br>}</font></p> <p><font size="2" face="Consolas">void Pills_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)<br>{<br> // Pills Collection Changed - do something<br>}</font><br></p></blockquote> <p>The issue I have encountered with this code is that setting that value of the Pills property directly does not always fire the CollectionChanged event.</p> <blockquote> <p><font size="2" face="Consolas">Pills = someOtherPillCollection;</font></p></blockquote> <p>What I did to work around this was to remove the property setter and only work with the collection through its properties. In this case, by using <a href="https://msdn.microsoft.com/en-us/library/ms132405(v=vs.110).aspx" target="_blank">Clear()</a> and <a href="https://msdn.microsoft.com/en-us/library/bb302894%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396" target="_blank">Concat<T>()</a>.</p> <blockquote> <p><font size="2" face="Consolas">Pills.Clear();<br>Pills.Concat<Pill>(someOtherPillCollection);</font></p></blockquote> <p>ObservableCollection does not have an AddRange() method. You could write your own extension method to do it, but I prefer to use the LINQ extension method Concat<T>().</p> <p>Has anyone else seen this same issue?</p> <p> </p> <div id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:a8e87627-c956-46e7-a73a-74fbb5374235" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/viewmodels" rel="tag">viewmodels</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com2tag:blogger.com,1999:blog-959852766553998174.post-77424105442066597302017-04-06T09:34:00.001-04:002017-04-06T09:34:45.169-04:00WPF Tip #8 - Grids and Rendering Performance<p>Today's tip is a quick one. It's about choosing the best panel for the layout of the <a href="https://msdn.microsoft.com/en-us/library/system.windows.uielement(v=vs.110).aspx" target="_blank">UIElements</a> in your WPF Window or Control.</p> <p>Many developers will default to putting everything into a <a href="https://msdn.microsoft.com/en-us/library/system.windows.controls.grid%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396" target="_blank">Grid</a>. It's easy. They're flexible and offer many layout options. When a Window is relatively simple and performance is not being analyzed by users or stakeholders, using Grids everywhere might be ok. However, professional WPF developers should make it a practice to learn the differences in features and performance of each panel and choose the best one for a particular layout scenario.</p> <p>In general, you should first try a <a href="https://msdn.microsoft.com/en-us/library/system.windows.controls.stackpanel(v=vs.110).aspx" target="_blank">StackPanel</a>. If you can accurately lay out your Window with StackPanels without a deep nested web of them, they are the best way to go. They are much faster than Grids in both measurement of elements and layout/arrangement.</p> <p>There are several other panels included in WPF. These are the most common, ranked from fastest to slowest (in general):</p> <ol> <li>Canvas</li> <li>StackPanel</li> <li>WrapPanel</li> <li>DockPanel</li> <li>Grid</li></ol> <p>This ranking is based on the <a href="http://stackoverflow.com/questions/9946811/in-what-order-are-panels-the-most-efficient-in-terms-of-render-time-and-performa/9996707#9996707" target="_blank">accepted answer</a> in <a href="http://stackoverflow.com/questions/9946811/in-what-order-are-panels-the-most-efficient-in-terms-of-render-time-and-performa" target="_blank">this StackOverflow question</a>. If you're interested in reading more about each of the panels and how they 'stack' up in different scenarios, I highly recommend reading the question and top answer.</p> <p>Cheers!</p> <p> </p> <div id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:22dcca1c-011d-4e63-a68d-e74ad646fd8d" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/xaml+layout" rel="tag">xaml layout</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-52695512084600623422017-03-30T13:03:00.001-04:002017-03-30T13:05:09.526-04:00WPF Tip #7 - Freeze WPF Freezable Objects from CodeIn <a href="http://www.wpf.tips/2017/03/wpf-tip-6-freeze-vector-image-resources.html" target="_blank">Tip #6</a>, we took a vector image resource and set it to Freeze = True in the XAML markup. Suppose that you need the resource to freeze at some point later in the application's execution. You can simply add this code to that point in the application:<br />
<blockquote>
<span style="font-family: Consolas;">If mySimpleImage.CanFreeze Then<br /> ' Makes the vector image frozen.<br /> mySimpleImage.Freeze()<br />End If</span></blockquote>
Yes, I'm giving VB some love in today's tip.<br />
<br />
Checking CanFreeze is necessary because not all <a href="https://msdn.microsoft.com/en-us/library/ms750509(v=vs.110).aspx" target="_blank">Freezable objects</a> can be frozen at every point in a WPF application's lifecycle. If Freeze() is called on an object that cannot currently be frozen, an exception will be thrown.<br />
<br />
<div class="wlWriterEditableSmartContent" id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:15536dcc-dc90-442b-8754-c0d1a56d6d3b" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/graphics" rel="tag">graphics</a>,<a href="http://del.icio.us/popular/xaml" rel="tag">xaml</a></div>
Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-60029604620763455682017-03-27T15:06:00.001-04:002017-03-27T15:09:01.810-04:00WPF Tip #6 - Freeze Vector Image ResourcesThe next several tips will examine <a href="https://msdn.microsoft.com/en-us/library/ms750509(v=vs.110).aspx" target="_blank">Freezable</a> objects. The description from MSDN:<br />
<br />
A Freezable is a special type of object that has two states: unfrozen and frozen. When unfrozen, a Freezable appears to behave like any other object. When frozen, a Freezable can no longer be modified.<br />
<br />
A few examples of WPF Freezable objects are Brushes, DrawingImages and Animation KeyFrames. If an application uses any of these resources and they are not going to be modified, they should be frozen. This will improve the performance of the application, as less processing will be used to re-render graphical elements.<br />
<br />
Here is a quick example of Freezing a <a href="https://msdn.microsoft.com/en-us/library/system.windows.media.drawingimage(v=vs.110).aspx" target="_blank">DrawingImage</a>. Consider vector graphics used in fixed-size elements on a window (toolbar buttons, for example). These are good candidates to be frozen.<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <DrawingImage x:Key="SimpleImage" presentationOptions:Freeze="True"></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <DrawingImage.Drawing></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <DrawingGroup></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <DrawingGroup.Children></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <GeometryDrawing Brush="Black"></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <GeometryDrawing.Geometry></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"/></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> </GeometryDrawing.Geometry></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <GeometryDrawing.Pen></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> <Pen Brush="Red" Thickness="2" /></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> </GeometryDrawing.Pen></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> </GeometryDrawing></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> </DrawingGroup.Children></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> </DrawingGroup></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> </DrawingImage.Drawing></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> </DrawingImage></span></span></blockquote>
<br />
<br />
Happy coding!<br />
<br />
<br />Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-80477691371746786832017-03-22T18:02:00.001-04:002017-03-22T18:02:48.298-04:00WPF Tip #5 - Data Binding with IMultiValueConverter<p>In <a href="http://www.wpf.tips/2017/03/wpf-tip-4-data-binding-with.html" target="_blank">Tip #4</a>, we examined the use of IValueConverter with WPF binding. If you are using <a href="https://msdn.microsoft.com/en-us/library/system.windows.data.multibinding(v=vs.110).aspx" target="_blank">MulitBinding</a>, a converter class that implements <a href="https://msdn.microsoft.com/en-us/library/system.windows.data.imultivalueconverter(v=vs.110).aspx" target="_blank">IMultiValueConverter</a> is needed.</p> <p>Like the IValueConverter, the class must implement Convert and ConvertBack methods. The difference being the multiple values come in as an <font face="Consolas">object[]</font> parameter in Convert() and go back out as an <font face="Consolas">object[]</font> return value in ConvertBack(). The following example takes two string values as input and returns them concatenated with a pipe '|'. It will convert them back using the Split function, assuming your text value contains no other pipes. </p> <blockquote> <p><font size="1" face="Consolas">public class TextAppendMultiConverter : IMultiValueConverter<br>{<br> public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)<br> {<br> return String.Concat(values[0], "|", values[1]);<br> }</font></p> <p><font size="1" face="Consolas"> public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)<br> {<br> return (value as string).Split('|');<br> }<br>}</font><br></p></blockquote> <p>This code will use the converter in a WPF TextBox's Text property MultiBinding.</p> <blockquote> <p><font size="1" face="Consolas"><TextBox><br> <TextBox.Text><br> <MultiBinding Converter="{StaticResource TextAppendMultiConverter}" FallbackValue="Busy loading..."><br> <Binding Path="IntroText"/><br> <Binding Path="ContentText"/><br> </MultiBinding><br> </TextBox.Text><br></TextBox></font><br></p></blockquote> <p>The FallbackValue will be displayed if the converter fails or data is unavailable in the attached DataContext.</p> <p>Next time, we will shift gears away from data binding. Happy coding!</p> <p> </p> <div id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:1a5ebc49-7028-4071-ab7b-dcb0956fd1ee" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/data+binding" rel="tag">data binding</a>,<a href="http://del.icio.us/popular/xaml" rel="tag">xaml</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0tag:blogger.com,1999:blog-959852766553998174.post-84622314030720004592017-03-16T12:52:00.001-04:002017-03-16T12:52:21.978-04:00WPF Tip #4 - Data Binding with IValueConverter<p>The first three tips have all been related to WPF data binding. Let's continue the theme with <a href="https://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter(v=vs.110).aspx" target="_blank">IValueConverter</a>. IValueConverter is used in conjunction with the <a href="https://msdn.microsoft.com/en-us/library/system.windows.data.binding.converterparameter(v=vs.110).aspx" target="_blank">Converter</a> parameter on a property's Binding.</p> <p>Converters are used whenever the type of the property being bound does not match the type of the property in the binding source. Converting a boolean value to <a href="https://msdn.microsoft.com/en-us/library/system.windows.visibility(v=vs.110).aspx" target="_blank">Visibility</a> enum value is the most common conversion throughout all Xaml code. It is so common that the .NET Framework has its own <a href="https://msdn.microsoft.com/en-us/library/system.windows.controls.booleantovisibilityconverter(v=vs.110).aspx" target="_blank">BooleanToVisibilityConverter</a> class that implements IValueConverter.</p> <p>To implement your own converter, simply create a class that implements the IValueConverter interface. The interface has two methods, Convert() and ConvertBack(). If your property will never update its binding source, the ConvertBack() method does not need to be implemented. If you leave the default code Visual Studio puts in newly generated methods to throw a NotImplementedException, you will quickly find out if the ConvertBack() method is necessary for your converter.</p> <p>This simple example is a variation on the BooleanToVisibilityConverter. It is an IndecisiveEnumToVisibilityConverter. Here is what my IndecisiveEnum looks like:</p> <blockquote> <p><font size="1" face="Consolas">public enum IndecisiveEnum<br>{<br> Yes,<br> Probably,<br> ThinkSo,<br> NotSure,<br> No,<br> WhyWouldAnyoneDoThat,<br> NotUnlessEveryoneElseIsDoingIt<br>}</font><br></p></blockquote> <p>The converter needs to take one of these values and return a Visibility. Here's the implementation of Convert() and ConvertBack().</p> <blockquote> <p><font size="1" face="Consolas">public object Convert(object value, Type targetType, object parameter, CultureInfo culture)<br>{<br> if (!(value is IndecisiveEnum))<br> return Visibility.Collapsed;</font></p> <p><font size="1" face="Consolas"> var typedValue = (IndecisiveEnum)value;</font></p> <p><font size="1" face="Consolas"> switch (typedValue)<br> {<br> case IndecisiveEnum.Yes:<br> case IndecisiveEnum.Probably:<br> case IndecisiveEnum.ThinkSo:<br> return Visibility.Visible;<br> case IndecisiveEnum.No:<br> case IndecisiveEnum.WhyWouldAnyoneDoThat:<br> return Visibility.Collapsed;<br> case IndecisiveEnum.NotUnlessEveryoneElseIsDoingIt:<br> return IsEveryoneElseDoingIt() ? Visibility.Visible : Visibility.Collapsed;<br> case IndecisiveEnum.NotSure: // return a 50/50 random chance of yes/no<br> Random gen = new Random();<br> int prob = gen.Next(100);<br> return prob <= 50 ? Visibility.Visible : Visibility.Collapsed;<br> default:<br> return Visibility.Collapsed;<br> }<br>}</font></p> <p><font size="1" face="Consolas">public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)<br>{<br> if (!(value is Visibility))<br> return IndecisiveEnum.No;</font></p> <p><font size="1" face="Consolas"> var typedValue = (Visibility)value;</font></p> <p><font size="1" face="Consolas"> switch (typedValue)<br> {<br> case Visibility.Collapsed:<br> case Visibility.Hidden:<br> return IndecisiveEnum.No;<br> case Visibility.Visible:<br> return IndecisiveEnum.Yes;<br> default:<br> return IndecisiveEnum.No;<br> }<br>}</font><br></p></blockquote> <p>For the IndecisiveEnum.NotUnlessEveryoneElseIsDoingIt value, the case calls a method which we'll pretend calls a web service to find out if everyone else is actually doing it or not. If the input value is NotSure, then a random call will return either Visible or Collapsed. Converting back is a little more straightforward.</p> <p>Consuming this converter in the WPF Xaml consists of two parts. First, the converter must be defined as a resource.</p> <blockquote> <p><font size="1" face="Consolas"><Window.Resources><br> <local:IndecisiveEnumToVisibilityConverter x:Key="IndecisiveEnumToVisibilityConverter" /><br></Window.Resources></font><br></p></blockquote> <p>Finally, the resource can be used in the binding for our TextBox Visibility property.</p> <blockquote> <p><font size="1" face="Consolas"><TextBox Visibility="{Binding IsVisible, Converter={StaticResource IndecisiveEnumToVisibilityConverter}}"/></font></p></blockquote> <p>That's it. Next time we'll look at the <a href="https://msdn.microsoft.com/en-us/library/system.windows.data.imultivalueconverter(v=vs.110).aspx" target="_blank">IMultiValueConverter</a>, which is used with MultiBinding.</p> <p> </p> <div id="scid:77ECF5F8-D252-44F5-B4EB-D463C5396A79:ae587892-aeb8-47cf-901a-13440602ac5a" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px">del.icio.us Tags: <a href="http://del.icio.us/popular/wpf" rel="tag">wpf</a>,<a href="http://del.icio.us/popular/data+binding" rel="tag">data binding</a>,<a href="http://del.icio.us/popular/mvvm" rel="tag">mvvm</a>,<a href="http://del.icio.us/popular/xaml" rel="tag">xaml</a></div>Alvin Ashcrafthttp://www.blogger.com/profile/04705298386808338562noreply@blogger.com0