topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • Monday August 3, 2020, 4:47 am
  • Proudly celebrating 15+ years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Author Topic: Wanted: Recommendations for learning WPF (with C#)  (Read 364 times)

Deozaan

  • Charter Member
  • Joined in 2006
  • ***
  • Points: 1
  • Posts: 9,088
    • View Profile
    • Donate to Member
Wanted: Recommendations for learning WPF (with C#)
« on: July 21, 2020, 08:00 PM »
I'd like to make a program with a UI. The content of the UI will not be static, but will change based on input from the user. What I mean by that is that the number of things shown can increase or decrease based on what the user does. For example, a to-do list might only show a few items, or it may show many items.

I'm thinking that since I program in C# I should use WPF for the UI. If anyone here is experienced with making GUI applications in C# and can tell me why I shouldn't go with WPF, I'd be glad to hear your reasons why and what alternative I should use.

Otherwise, I'm looking for recommendations on good resources for learning how to use WPF to make GUI applications. Free is preferred. And I think I'd prefer the information in written/image format (e.g., a book or website) rather than video format. But I'm open to hearing any useful suggestions or recommendations of learning materials people here have found useful.

Thanks in advance!
« Last Edit: July 21, 2020, 11:17 PM by Deozaan »

wraith808

  • Supporting Member
  • Joined in 2006
  • **
  • default avatar
  • Posts: 10,577
    • View Profile
    • Donate to Member
Re: Wanted: Recommendations for learning WPF (with C#)
« Reply #1 on: July 21, 2020, 09:53 PM »
Are you tied to desktop?  That's the only reason I can think of for not using WPF.  If it's desktop, I'd definitely recommend it, and look into MVVM- that's what I use for a more reactive interface and to decouple the interface from the logic.  It seems like it might be a good thing for your use case.

As far as learning- I'd personally suggest using XAML instead of the visual editor.  Just like with other visual editors, the WPF design canvas can create some pretty shitty code.  And when you need to do something, you find that it screws with the whole interface.

If you want to start with the visual editor, there are a variety of courses:

https://www.wpftutor...earnWPFin14Days.html
https://www.wpf-tutorial.com/
https://www.guru99.com/wpf-tutorial.html
https://www.tutorial...nt.com/wpf/index.htm

That's just a few of them.  Of those, I like wpf-tutorial.com the best.  There are better paid ones, but that one does the job.  I'd also suggest https://www.c-sharpc...cepts-in-15-minutes/ after that, to reinforce some of the concepts, no matter which one you choose.

If you want to go the XAML route, I'd go with tutorialspoint - https://www.tutorial...t.com/xaml/index.htm

That rolls in all of the concepts for that c-sharpcorner article also, making it an unnecessary read at that point.

One thing to note- all of these are pretty old.  Other than the format of visual studio, that shouldn't matter though.

Deozaan

  • Charter Member
  • Joined in 2006
  • ***
  • Points: 1
  • Posts: 9,088
    • View Profile
    • Donate to Member
Re: Wanted: Recommendations for learning WPF (with C#)
« Reply #2 on: July 21, 2020, 11:58 PM »
I'm not necessarily tied to Desktop, and there's a part of me that kind of likes the idea of being able to access the information from various devices or even collaboratively with others. But I have no idea how to do any of that, aside from making it web-based, and I don't really enjoy making web front-end stuff, or back-end server stuff for that matter. I suppose I could just write it in Unity, which I'm familiar enough with the UI system and it has built-in cross-platform build support. But it seemed like a waste of computing resources to use a 3D game engine to run what is (or should be) a simple, lightweight GUI application. So I'll be happy to settle for a "portable" desktop app I can run and maybe sync via Dropbox if I need to access it across devices or share it with others. Hence my foray into WPF. If I get really serious about the idea of running it on mobile devices at some future time, then maybe I'll try porting the code back into Unity or come up with some other plan. I'll cross that bridge when/if I ever get that far.

So, thanks for the links, wraith808! I'll start looking through them.



In the meantime, here are some other resources I've looked at, in case it helps others who may come across this thread in the future.

At the beginning of this year, I wanted to clean up a GUI app I had hacked together for (NANY 2018) using the visual editor when I had absolutely no idea what I was doing, so I searched for some tutorial videos on YouTube and came across Tim Corey's channel. I watched a few of his videos, including:

Intro to WPF: Learn the basics and best practices of WPF for C#


I found the above video to be a good primer on WPF. It, too, recommended typing in the XAML manually rather than using the visual editor. After I finished that one, I wanted to learn more and the next suggested video from his channel was:

WPF in C# with MVVM using Caliburn Micro


I don't think I finished watching all of the above video, mostly because I was such a noob a lot of it was going over my head, and it seemed like a lot of time and effort to learn about MVVM when all I really wanted at the time was to fix a few relatively minor issues with my hacked together GUI on my older program.

With both of those videos being over an hour long, I was afraid of asking for more video tutorials here because I didn't like the idea of spending 40-60 hours watching a video course/tutorial to learn. But I thought that perhaps other tutorial videos could exist that didn't require such a time commitment or at least divided up the content into relatively more bite-sized chunks. So today I did another search looking for comprehensive, but short(er) videos. What I found appears to reinforce my initial suspicion that video tutorials will require a fairly significant time investment. For example, I found this 45-video playlist by AngelSix on YouTube, where each video appears to be approximately 1 hour long on average.

WPF UI Programming


I did watch that first video in the series and it also recommended writing the XAML manually for similar reasons. Video #3 in the playlist will cover some MVVM basics as well, so that means three out of three sources so far have recommended writing XAML directly and using MVVM.
« Last Edit: July 22, 2020, 11:54 AM by Deozaan »

wraith808

  • Supporting Member
  • Joined in 2006
  • **
  • default avatar
  • Posts: 10,577
    • View Profile
    • Donate to Member
Re: Wanted: Recommendations for learning WPF (with C#)
« Reply #3 on: July 22, 2020, 07:50 AM »
Though he calls using your own MVVM framework like "Building a car in order to drive it," taking a brief look at that video, it's a lot harder than what I do to configure that framework.  I'll try to write something simple I can put on github that illustrates how I do it.  No promises on the timeline though... unfortunately, I have a lot on my plate right now.

One other thing I'll say, and I'm not sure that most of the tutorials recommend it though it's the way I've started writing my XAML in most cases - make liberal use of DockPanel and StackPanel.  They make organizing your controls a lot simpler, IMO.

Deozaan

  • Charter Member
  • Joined in 2006
  • ***
  • Points: 1
  • Posts: 9,088
    • View Profile
    • Donate to Member
Re: Wanted: Recommendations for learning WPF (with C#)
« Reply #4 on: July 22, 2020, 11:54 AM »
I'll try to write something simple I can put on github that illustrates how I do it.  No promises on the timeline though... unfortunately, I have a lot on my plate right now.

If you can manage it, great! If not, no worries. My foray into WPF is mostly to satisfy my curiosity or learn a new skill as a hobby than for anything immediately important.


One other thing I'll say, and I'm not sure that most of the tutorials recommend it though it's the way I've started writing my XAML in most cases - make liberal use of DockPanel and StackPanel.  They make organizing your controls a lot simpler, IMO.

The first video in the above AngelSix WPF UI Programming playlist says he thinks of virtually everything in terms of either Grid or StackPanel. I'm unfamiliar with the DockPanel, but I'll be sure to learn more about it to see how it can be useful. Thanks for the tip!


Deozaan

  • Charter Member
  • Joined in 2006
  • ***
  • Points: 1
  • Posts: 9,088
    • View Profile
    • Donate to Member
Re: Wanted: Recommendations for learning WPF (with C#)
« Reply #5 on: July 22, 2020, 02:01 PM »
I wasn't sure how far into reading the text tutorials I'd have to go before being ready for the MVVM concept, so I decided to watch the next two videos by AngelSix since they build upon each other and the last of which is a video introducing MVVM. In it, he writes the MVVM from scratch rather than using something like Caliburn.Micro, which is what Tim Corey uses and recommends.

C# WPF UI Tutorials: 03 - View Model MVVM Basics


It definitely seems a lot simpler to me than what I recall from the Tim Corey MVVM video which I watched in January. And maybe it's close enough to what you had in mind, wraith808, that it will save you the trouble of having to write up your example project on GitHub. :Thmbsup:

wraith808

  • Supporting Member
  • Joined in 2006
  • **
  • default avatar
  • Posts: 10,577
    • View Profile
    • Donate to Member
Re: Wanted: Recommendations for learning WPF (with C#)
« Reply #6 on: July 22, 2020, 10:55 PM »
It looks a lot closer to what I do, though I do something different than using nameof(class) in order to not have to worry about naming errors that doesn't rely on intellisense.  This is an example of one of my viewmodels that I've written:

Code: C# [Select]
  1. public class ConfigurationViewModel: INotifyPropertyChanged
  2.     {
  3.         public ConfigurationSettingsModel Model { get; set; }
  4.  
  5.         public ConfigurationViewModel(ConfigurationSettingsModel model)
  6.         {
  7.             this.Model = model;
  8.             // create commands
  9.             this.OkCommand = new RelayCommand(param => this.OkCommandExecute(), param => this.CanOk);
  10.             this.CancelCommand = new RelayCommand(param => this.CancelCommandExecute(), param => this.CanCancel);
  11.         }
  12.  
  13.         #region Commands
  14.  
  15.         #region OkCommand
  16.  
  17.         public ICommand OkCommand
  18.         {
  19.             get;
  20.             internal set;
  21.         }
  22.  
  23.         private bool CanOk
  24.         {
  25.             get
  26.             {
  27.                 return this.ValidateSettings();
  28.             }
  29.         }
  30.  
  31.         public void OkCommandExecute()
  32.         {
  33.             this.Model.SaveSettings();
  34.             this.DialogResult = true;
  35.         }
  36.  
  37.         #endregion
  38.  
  39.         #region CancelCommand
  40.  
  41.         public ICommand CancelCommand
  42.         {
  43.             get;
  44.             internal set;
  45.         }
  46.  
  47.         private bool CanCancel
  48.         {
  49.             get
  50.             {
  51.                 return true;
  52.             }
  53.         }
  54.  
  55.         public void CancelCommandExecute()
  56.         {
  57.             this.Model.RefreshData();
  58.             this.DialogResult = false;
  59.         }
  60.  
  61.         #endregion
  62.  
  63.         #endregion
  64.  
  65.         #region Observable Properties
  66.  
  67.         private bool? _DialogResult = null;
  68.         public bool? DialogResult
  69.         {
  70.             get
  71.             {
  72.                 return this._DialogResult;
  73.             }
  74.             set
  75.             {
  76.                 if (value != this._DialogResult)
  77.                 {
  78.                     this._DialogResult = value;
  79.                     this.NotifyPropertyChanged(() => this.DialogResult);
  80.                 }
  81.             }
  82.         }
  83.  
  84.         #endregion
  85.  
  86.         #region Helper Methods
  87.  
  88.         private bool ValidateSettings()
  89.         {
  90.             return true;
  91.         }
  92.  
  93.         #endregion
  94.  
  95.  
  96.         #region INotifyPropertyChanged Implementation
  97.  
  98.         public event PropertyChangedEventHandler PropertyChanged;
  99.  
  100.         protected virtual void OnPropertyChanged(string propertyName)
  101.         {
  102.             PropertyChangedEventHandler handler = this.PropertyChanged;
  103.             if (handler != null)
  104.             {
  105.                 var e = new PropertyChangedEventArgs(propertyName);
  106.                 handler(this, e);
  107.             }
  108.         }
  109.  
  110.         protected void NotifyPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
  111.         {
  112.             var lambda = (LambdaExpression)property;
  113.             MemberExpression memberExpression;
  114.  
  115.             if (lambda.Body is UnaryExpression)
  116.             {
  117.                 var unaryExpression = (UnaryExpression)lambda.Body;
  118.                 memberExpression = (MemberExpression)unaryExpression.Operand;
  119.             }
  120.             else
  121.                 memberExpression = (MemberExpression)lambda.Body;
  122.  
  123.             this.OnPropertyChanged(memberExpression.Member.Name);
  124.         }
  125.  
  126.         #endregion


But I will say that guy does seem to break it down a lot better than the first video that I saw, and I think his methods would be worth following from what I saw.

I didn't notice what he did for a bootstrapper, but I use the simple expident of making use of a couple of properties of the app.xaml.

In the app.xaml, I set it up like so:

Code: C# [Select]
  1. <Application x:Class="ApplicationName.App"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.              Startup="Application_Startup"
  5.              SessionEnding="App_SessionEnding">
  6.     <Application.Resources>
  7.          
  8.     </Application.Resources>
  9. </Application>

Normally that startup is set to the first form- but this gives me a chance to go into the bootstrapper.

Then in the app.xaml.cs, I set up those two events.  The startup event is below.

Code: C# [Select]
  1. private void Application_Startup(object sender, StartupEventArgs e)
  2.         {
  3.             this.RequestClose = false;
  4.             this.SettingsConfiguration = this.GetConfiguration();
  5.             this.SettingsModel = new ConfigurationSettingsModel(this.SettingsConfiguration);
  6.  
  7.             this.ViewModel = new MainViewModel(this.SettingsModel);
  8.             this.View = new MainView(this.ViewModel);
  9.  
  10.             this.View.Closing += this.OnClosing;
  11.  
  12.             this.ViewModel.RequestConfigurationDialog += new EventHandler(ViewModel_RequestConfigurationDialog);
  13.             this.ViewModel.RequestShowAboutDialog += new EventHandler(ViewModel_RequestShowAboutDialog);
  14.  
  15.             // When the ViewModel asks to be closed, it closes the window via attached behaviour.
  16.             // We use this event to shut down the remaining parts of the application
  17.             this.ViewModel.RequestClose += delegate
  18.             {
  19.                 // Make sure close down event is processed only once
  20.                 if (this.RequestClose == false)
  21.                 {
  22.                     this.RequestClose = true;
  23.  
  24.                     // Save session data and close application
  25.                     this.OnClosed(this.ViewModel, this.View);
  26.                 }
  27.             };
  28.  
  29.             this.InitializeViewCommandBindings();  // Initialize RoutedCommand bindings
  30.             this.View.Show();
  31.         }
  32.  
  33.         private void App_SessionEnding(object sender, SessionEndingCancelEventArgs e)
  34.         {
  35.             e.Cancel = this.OnSessionEnding();
  36.         }
  37.  
  38.         private bool OnSessionEnding()
  39.         {
  40.             if (this.ViewModel != null)
  41.             {
  42.                 if (this.ViewModel.CanClose == false)
  43.                 {
  44.                     MessageBox.Show("Application is not ready to exit.",
  45.                                     "Cannot exit application", MessageBoxButton.OK);
  46.  
  47.                     return !this.ViewModel.CanClose; // Cancel close down request if ViewModel is not ready, yet
  48.                 }
  49.  
  50.                 return !this.ViewModel.CanClose; // Cancel close down request if ViewModel is not ready, yet
  51.             }
  52.  
  53.             return true;
  54.         }
  55.  
  56.         private void OnClosed(MainViewModel viewModel, MainView view)
  57.         {
  58.             // Persist data here
  59.             this.SettingsModel.SaveSettings();
  60.  
  61.             Application.Current.Shutdown();
  62.         }

There's a bit more to it- but I thought that knowing how the bootstrapper is set up and an alternate way to hook up the INotifyPropertyChanged might be of benefit to perhaps encapsulate in what he refers to in the video.
« Last Edit: July 22, 2020, 11:05 PM by wraith808 »