日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

WPF/MVVM 快速开发

發(fā)布時間:2023/12/4 asp.net 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WPF/MVVM 快速开发 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial

?

這篇文章醍醐灌頂,入門良藥啊!

?

Introduction

Assuming that you have a decent understanding of C#, getting started in WPF isn't too difficult. I started looking at WPF a while ago, and didn't find many helpful MVVM tutorials. Hopefully this article addresses that.

As with learning any new technology, you get the benefit of hindsight. From my perspective, almost every tutorial on WPF I've come across is inadequate for one of several reasons:

  • The example is all in XAML.
  • The example glosses over the key facts that would actually make your life easier.
  • The example tries to show off WPF/XAML's capabilities with lots of pointless effects that aren't helping you.
  • The example uses classes that have properties that appear far too similar to framework keywords and classes, and are therefore difficult to identify in the (XAML) code as being user defined (the?ListBox GroupStyle's?Name?attribute is a complete headache for novices).

So to address this, I've written this based on what I would have liked to have found as the #1 hit on Google after typing 'WPF Tutorial'. This article may not be 100% correct, or even do things 'the one true way', but it will illustrate the main points that I wish I had found in one place 6 months ago.

I will quickly introduce some topics, then show an example that explains or demonstrates each point. Accordingly, I haven't really attempted to make the GUIs pretty, that's not the point of this article (see the bullet points above).

As this tutorial is quite long, I've elided quite a lot of code for brevity, so please download the attached zip file, and look at the examples (.NET 4.0/VS2010).?Each example builds on the previous one.

The Basics

  • The most important thing about WPF is data binding. In short, you have some data, typically in a collection of some sort, and you want to display it to the user. You can 'bind' your XAML to the data.
  • WPF has two parts, the XAML which describes your GUI layout and effects, and the code-behind that is tied to the XAML.
  • The neatest and probably most reusable way to organise your code is to use the 'MVVM' pattern: Model, View, ViewModel. This has the aim of ensuring that your View contains minimal (or no) code, and should be XAML-only.
  • The Key Points You Need to Know

  • The collection you should use to hold your data is the?ObservableCollection<>. Not a?list, not adictionary, but an?ObservableCollection. The word 'Observable' is the clue here: the WPF window needs to be able to 'observe' your data collection. This collection class implements certain interfaces that WPF uses.
  • Every WPF control (including 'Window's) has a 'DataContext' and?Collection?controls have an 'ItemsSource' attribute to bind to.
  • The interface 'INotifyPropertyChanged' will be used extensively to communicate any changes in the data between the GUI and your code.
  • Example 1: Doing It (mostly) Wrong

    The best way to start is an example. We will start with a?Song?class, rather than the usual?Person?class. We can arrange songs into Albums, or one large collection, or by Artist. A simple?Song?class would be as follows:

    Hide???Copy Code public class Song {#region Membersstring _artistName;string _songTitle;#endregion #region Properties /// The artist name. public string ArtistName { get { return _artistName; } set { _artistName = value; } } /// The song title. public string SongTitle { get { return _songTitle; } set { _songTitle = value; } } #endregion }

    In WPF terminology, this is our 'Model'. The GUI is our 'View'. The magic that data binds them together is our 'ViewModel', which is really just an adapter that turns our Model into something that the WPF framework can use. So just to reiterate, this is our 'Model'.

    Since we've created a?Song?as a reference type, copies are cheap and light on memory. We can create ourSongViewModel?quite easily. What we need to consider first is, what are we going to (potentially) display? Suppose we just care about the?song's artist name, not the?song?title, then the?SongViewModel?could be defined as follows:

    Hide???Copy Code public class SongViewModel {Song _song;public Song Song{get{return _song;}set { _song = value; } } public string ArtistName { get { return Song.ArtistName; } set { Song.ArtistName = value; } } }

    Except that this isn't quite correct. Since we're exposing a property in our?ViewModel, we would obviously want a change to the?song's artist name made in the code to be automatically shown in the GUI, and vice versa:

    Hide???Copy Code SongViewModel song = ...; // ... enable the databinding ... // change the name song.ArtistName = "Elvis"; // the gui should change

    Notice that in all the examples here, we create our view model *declaratively*, i.e., we do this in the XAML:

    Hide???Copy Code <Window x:Class="Example1.MainWindow"xmlns:local="clr-namespace:Example1"> <Window.DataContext> <!-- Declaratively create an instance of our SongViewModel --> <local:SongViewModel /> </Window.DataContext>

    This is equivalent to doing this in your code-behind?MainWindow.cs:

    Hide???Copy Code public partial class MainWindow : Window {SongViewModel _viewModel = new SongViewModel();public MainWindow(){InitializeComponent();base.DataContext = _viewModel; } }

    And removing your?DataContext?element in the XAML:

    Hide???Copy Code <Window x:Class="Example1.MainWindow"xmlns:local="clr-namespace:Example1"> <!-- no data context -->

    This is our view:

    Clicking the button does not update anything, because we have not completely implemented data binding.

    Data Binding

    Remember I said at the start that I would choose a property that stands out. In this example, we want to display the?ArtistName. I chose this name because it is?NOT?the same as any WPF attribute. There are a countless number of examples on the web that choose a?Person?class and then a?Name?attribute (the?Name?attribute exists on multiple .NET WPF classes). Perhaps the authors of the articles just don't realise that this is particularly confusing for beginners (who are, curiously enough, the target audience of these articles).

    There are dozens of other articles about data binding out there, so I won't cover it here. I hope the example is so trivial that you can see what is going on.

    To bind to the?ArtistName?property on our?SongViewModel, we simply do this in the?MainWindow.xaml:

    Hide???Copy Code <Label Content="{Binding ArtistName}" />

    The 'Binding' keyword binds the content of the control, in this case a?Label, to the property 'ArtistName' of the object returned by?DataContext. As you saw above, we set our?DataContext?to an instance ofSongViewModel, therefore we are effectively displaying?_songViewModel.ArtistName?in the?Label.

    Once again:?clicking the button does not update anything, because we have not completely implemented data binding. The GUI is not receiving any notifications that the property has changed.

    Example 2: INotifyPropertyChanged

    This is where we have to implement the cunningly named interface:?INotifyPropertyChanged. As it says, any class that implements this interface, notifies any listeners when a property has changed. So we need to modify our?SongViewModel?class a little bit more:

    Hide???Shrink????Copy Code public class SongViewModel : INotifyPropertyChanged{#region Construction/// Constructs the default instance of a SongViewModelpublic SongViewModel() { _song = new Song { ArtistName = "Unknown", SongTitle = "Unknown" }; } #endregion #region Members Song _song; #endregion #region Properties public Song Song { get { return _song; } set { _song = value; } } public string ArtistName { get { return Song.ArtistName; } set { if (Song.ArtistName != value) { Song.ArtistName = value; RaisePropertyChanged("ArtistName"); } } } #endregion #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion #region Methods private void RaisePropertyChanged(string propertyName) { // take a copy to prevent thread issues PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } #endregion }

    There are several things now happening here. Firstly, we check to see if we are going to really change the property: this improves performance slightly for more complex objects. Secondly, if the value has changed, we raise the?PropertyChanged?event to any listeners.

    So now we have a?Model, and a?ViewModel. We just need to define our?View. This is just our?MainWindow:

    Hide???Copy Code <Window x:Class="Example2.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:Example2" Title="Example 2" SizeToContent="WidthAndHeight" ResizeMode="NoResize" Height="350" Width="525"> <Window.DataContext> <!-- Declaratively create an instance of our SongViewModel --> <local:SongViewModel /> </Window.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Label Grid.Column="0" Grid.Row="0" Content="Example 2 - this works!" /> <Label Grid.Column="0" Grid.Row="1" Content="Artist: " /> <Label Grid.Column="1" Grid.Row="1" Content="{Binding ArtistName}" /> <Button Grid.Column="1" Grid.Row="2" Name="ButtonUpdateArtist" Content="Update Artist Name" Click="ButtonUpdateArtist_Click" /> </Grid> </Window>

    To test the databinding, we can take the traditional approach and create a button and wire to its?OnClick?event, so the XAML above has a button, and?Click?event, giving the code behind:

    Hide???Copy Code public partial class MainWindow : Window {#region MembersSongViewModel _viewModel;int _count = 0; #endregion public MainWindow() { InitializeComponent(); // We have declared the view model instance declaratively in the xaml. // Get the reference to it here, so we can use it in the button click event. _viewModel = (SongViewModel)base.DataContext; } private void ButtonUpdateArtist_Click(object sender, RoutedEventArgs e) { ++_count; _viewModel.ArtistName = string.Format("Elvis ({0})", _count); } }

    This is ok, but it is not how we should use WPF: firstly, we have added our 'update artist' logic into our code-behind. It does not belong there. The?Window?class is concerned with windowing. The second problem is, suppose we want to move logic in the *button* click event to a different control, for example, making it a menu entry. It means we will be cut'n'pasting, and editing in multiple places.

    Here is our improved view, where clicking now works:

    Example 3: Commands

    Binding to GUI events is problematic. WPF offers you a better way. This is?ICommand. Many controls have aCommand?attribute. These obey binding in the same way as?Content?and?ItemsSource, except you need to bind it to a *property* that returns an?ICommand. For the trivial example that we are looking at here, we just implement a trivial class called 'RelayCommand' that implements?ICommand.

    ICommand?requires the user to define two methods:?bool CanExecute, and?void Execute. The?CanExecutemethod really just says to the user, can I execute this command? This is useful for controlling the context in which you can perform GUI actions. In our example, we don't care, so we return?true, meaning that the framework can always call our 'Execute' method. It could be that you have a situation where you have a command bound to button, and it can only execute if you have selected an item in a list. You would implement that logic in the 'CanExecute' method.

    Since we want to reuse the?ICommand?code, we use the?RelayCommand?class that contains all the repeatable code we do not want to keep writing.

    To show how easy it is to reuse the?ICommand, we bind the Update Artist command to both a button and a menu item. Notice that we no longer bind to Button specific Click event, or Menu specific Click event.

    Example 4: Frameworks

    By now, if you have read closely, you'll probably notice that a lot of this is just repetitive code: raising INPC, or creating commands. This is mostly boilerplate, and for INPC, we can move it to base class that we call 'ObservableObject'. For the?RelayCommand?class, we just move that into our .NET class library. This is how all of the MVVM frameworks you find on the web begin (Prism, Caliburn, etc.).

    As far as the?ObservableObject?and?RelayCommand?classes are concerned, they are rather basic and are the inevitable result of refactoring. Unsurprisingly, these classes are practically the same as those by?Josh Smith.

    So we move these classes into a small class library that we can reuse in future.

    The view looks much the same as before:

    Example 5: Collections of Songs, Doing It Wrong

    As I said before, in order to display collections of items in your?View?(i.e. the XAML), you need to use anObservableCollection. In this example, we create an?AlbumViewModel, which nicely collects our songs together in something that people understand. We also introduce a simple song database, purely so we can quickly produce some song information for this example.

    Your first attempt might be as follows:

    Hide???Copy Code class AlbumViewModel {#region MembersObservableCollection<Song> _songs = new ObservableCollection<Song>();#endregion }

    You might think: "I have a different view model this time, I want to display the songs as an?AlbumViewModel, not a?SongViewModel".

    We also create some more?ICommands?and attach them to some buttons:

    Hide???Copy Code public ICommand AddAlbumArtist {}public ICommand UpdateAlbumArtists {}

    In this example, clicking 'Add Artist' works fine. But clicking 'Update Artist Names', fails. If you read the yellow highlighted note on this?page on MSDN, it explains why:

    To fully support transferring data values from binding source objects to binding targets, each object in your collection that supports bindable properties must implement an appropriate property changed notification mechanism such as the?INotifyPropertyChanged?interface.

    Our view looks like this:

    Example 6: Collections of Songs, the Right Way

    In this final example, we fix the?AlbumViewModel?to have an?ObservableCollection?of?SongViewModelsthat we created earlier:

    Hide???Copy Code class AlbumViewModel {#region MembersObservableCollection<SongViewModel> _songs = new ObservableCollection<SongViewModel>();#endregion// code elided for brevity }

    Now all our buttons that are bound to commands operate on our collection.?Our code-behind inMainWindow.cs?is still completely empty.

    Our view looks like this:

    ?

    Conclusion

    Instantiating Your ViewModel

    One last point that is worth mentioning is that when you declare your?ViewModel?declaratively in the XAML, you cannot pass it any parameters: in other words, your?ViewModel?must have an implicit, or explicit default constructor. How you add state to your?ViewModel?is up to you. You may find it easier to declare theViewModel?in the?MainWindow.cs?code-behind, where you can pass in construction parameters.

    Other Frameworks

    There are lots of other?MVVM Frameworks?of wildly different complexity and functionality, targeting WPF, WP7, Silverlight, and any combination of the three.

    Finally...

    Hopefully these six examples show you how easy it is to write a WPF application using MVVM. I've tried to cover all of the points that I think are important and often discussed in multiple articles.

    If you find this article helpful, please feel to vote it up.

    If you find faults in this article, or I've said anything wrong, or you have some other issue with it, please leave a comment below explaining why, and how you would fix it.

    轉(zhuǎn)載于:https://www.cnblogs.com/smartsensor/p/5066471.html

    總結(jié)

    以上是生活随笔為你收集整理的WPF/MVVM 快速开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。