Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.147.6.122] |
|
Сообщ.
#1
,
|
|
|
По просьбам товарищей с форума приведу некоторые аргументы, сугубо по моему мнению, почему WPF более удобней и функциональней чем WindowsForms. А начну я свое сравнений с небольшой цитаты с форума RSDN, ибо лучше и лаконичней выразиться вероятно у меня не получиться.
Цитата Преимущества для меня: 1. Декларативность. Писать в XAML реально нагляднее и удобнее. 2. Свойства зависимостей и маршрутизируемые события. Такого хотелось очень давно, наконец оно есть. 3. Шаблоны. Здесь лучше смотреть примеры. На, мой взгляд, уже одна эта фича кладет WinForms и WinAPI на обе лопатки. 4. Простая и в то же время мощная система биндингов с возможностью соединять большинство свойств в обе стороны. 5. Встроенная анимация на основе свойств. Оно действительно работает классно. Вообще можно перечислить еще много чего. Лучше глянуть какой-нибудь Overview и понять, подходит или нет. Лично я еще ни разу не пожалел о переходе на WPF и обратно на WinForms не тянет соооовсем. А теперь попробую долить воды на эту раскручивающуюся мельницу. Во первых я не хочу в этой статье рассказывать про то как происходит отрисовка элементов форм в GDI и WPF так как этому посвящено множество слов в различной литературе и статьях посвященных WPF, а попробую рассмотреть все с практической стороны. Во первых одна из основных целей при разработке приложений я считаю что это разработка масштабируемого и понятного кода. Что нам дает с этой стороны WindowsForms? Ну во первых это широко принятый стиль смешивать в коде формы все на свете: логику и обработку данных, работу с источниками данных, заполнение полей и контролов. В итоге мы получаем полную кашу из кода взглянув на который спустя некоторое время приходишь в ужас, потому как добавление дополнительного функционала приводит к переписыванию кучи кода. Возможно я немного преувеличиваю, но из всего что я видел так и не увидел красивого и масштабируемого кода, да и у самого не особо получалось. А WPF с другой стороны решает часть этих проблем. Рассмотрим пример: WindowsForms namespace WinFormsSample { public partial class MainForm : Form { public MainForm() { InitializeComponent(); textBox1.Text = "test"; } } } и WPF <Window x:Class="WPF_Sample.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF_Sample" Height="300" Width="300" > <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBox Text="{Binding TextData}"/> </Grid> </Window> namespace WPF_Sample { public partial class Window1 { public string TextData { get; set; } public Window1() { InitializeComponent(); TextData = "test"; DataContext = this; } } } На первый взгляд в обоих случаях код примерно одинаковый, но если учитывать более сложный вариант, например заполнение некоего списка то в WindowsForms случае в коде окна придется весь процесс заполнения и обработки списка описывать руками, причем смешивая логику представления с логикой получения и обработки данных. WindowsForms код я в следующем примере писать не буду, а покажу как это будет в WPF, кто пользуется WindowsForms сам может попробовать сделать тоже и почувствовать разницу. <?xml version="1.0" encoding="utf-8"?> <Window x:Class="WPF_Sample.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF_Sample" Height="300" Width="300"> <Grid> <Grid.Resources> <!--заготовка детализованного отображения списка--> <ControlTemplate x:Key="Selected" TargetType="{x:Type ListViewItem}"> <Border Background="LightYellow" BorderBrush="Black" BorderThickness="1" CornerRadius="5"> <StackPanel> <GridViewRowPresenter TextBlock.FontWeight="Bold" Content="{TemplateBinding Content}" Columns="{TemplateBinding GridView.ColumnCollection}" /> <StackPanel Orientation="Vertical"> <DockPanel> <TextBlock FontWeight="Bold" Margin="5">Длина</TextBlock> <TextBlock Text="{Binding Param1}" VerticalAlignment="Center"/> </DockPanel> <DockPanel> <TextBlock FontWeight="Bold" Margin="5">Материал</TextBlock> <TextBlock Text="{Binding Param2}" VerticalAlignment="Center"/> </DockPanel> </StackPanel> </StackPanel> </Border> </ControlTemplate> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBox Text="{Binding TextData}" /> <!--описываем таблицу и указываем связь с коллекцией данных--> <ListView Grid.Row="1" ItemsSource="{Binding Data}"> <ListView.View> <!--задатем тип отображения списка--> <GridView> <!--описываем колонки таблицы и указываем связи с полями объекта--> <GridViewColumn Width="160" DisplayMemberBinding="{Binding Name}" Header="Наименование" /> <GridViewColumn Width="80" DisplayMemberBinding="{Binding Qty}" Header="Кол-во" /> <GridViewColumn Width="80" DisplayMemberBinding="{Binding Price, StringFormat=c, ConverterCulture='Ru-ru'}" Header="Цена" /> </GridView> </ListView.View> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Style.Triggers> <!--стили отображения описанные в простеньком триггере--> <Trigger Property="IsSelected" Value="True"> <!--триггер показывающий детализацию объекта при выборе в списке--> <Setter Property="Template" Value="{StaticResource Selected}" /> </Trigger> <!--триггеры разукрашивающие строки в зависимости от способа поставки, в упаковке или нет--> <DataTrigger Binding="{Binding IsPackaged}" Value="True"> <Setter Property="Background"> <Setter.Value> <LinearGradientBrush EndPoint="0.494,0.889" StartPoint="0.494,0.028"> <GradientStop Color="#2299FF99" Offset="0" /> <GradientStop Color="#FF99FF99" Offset="1" /> </LinearGradientBrush> </Setter.Value> </Setter> </DataTrigger> <DataTrigger Binding="{Binding IsPackaged}" Value="False"> <Setter Property="Background"> <Setter.Value> <LinearGradientBrush EndPoint="0.494,0.889" StartPoint="0.494,0.028"> <GradientStop Color="#3FFF1111" Offset="0" /> <GradientStop Color="#FFFF9999" Offset="1" /> </LinearGradientBrush> </Setter.Value> </Setter> </DataTrigger> </Style.Triggers> </Style> </ListView.ItemContainerStyle> </ListView> </Grid> </Window> namespace WPF_Sample { public partial class Window1 : Window { public string TextData { get; set; } public ObservableCollection<SomeData> Data { get; set; } public Window1() { InitializeComponent(); TextData = "test"; //здесь мы эмулируем генерацию и обработку данных Data = new ObservableCollection<SomeData> { new SomeData {Name = "Винт М8", Qty = 100, Price = 5, Param1 = "20 mm", Param2 = "Сталь", IsPackaged = true}, new SomeData {Name = "Винт М8", Qty = 100, Price = 7, Param1 = "25 mm", Param2 = "Нержавейка", IsPackaged = true}, new SomeData {Name = "Винт М10", Qty = 100, Price = 7, Param1 = "30 mm", Param2 = "Сталь", IsPackaged = false}, new SomeData {Name = "Винт М10", Qty = 100, Price = 12, Param1 = "40 mm", Param2 = "Нержавейка", IsPackaged = true}, new SomeData {Name = "Винт М12", Qty = 100, Price = 14, Param1 = "30 mm", Param2 = "Сталь", IsPackaged = false}, new SomeData {Name = "Винт М12", Qty = 100, Price = 16, Param1 = "60 mm", Param2 = "Нержавейка", IsPackaged = false}, new SomeData {Name = "Винт М14", Qty = 100, Price = 44, Param1 = "50 mm", Param2 = "Сталь", IsPackaged = false}, new SomeData {Name = "Винт М14", Qty = 100, Price = 67, Param1 = "55 mm", Param2 = "Нержавейка", IsPackaged = true} }; DataContext = this; } } public class SomeData { public string Name { get; set; } public int Qty { get; set; } public decimal Price { get; set; } public string Param1 { get; set; } public string Param2 { get; set; } public bool IsPackaged { get; set; } } } Как видно из приведенного примера в XAML коде мы можем уместить все описание представления, а в коде формы остается чистая работа с данными. Код данного примера я прикреплю к топику чтобы вы сами могли поэкспериментировать. Пока этим примером я завершу данную статью, потому как рассказать еще много чего хочется но сваливать все в одну кучу не очень хочется. Далее хотелось бы описать принцип паттерна MVC и рассмотреть пример его использования в WindowsForms и WPF. Скажу еще одно, в данном примере я немного схитрил (лишь ради того чтобы не загромождать код), те кто читал мою статью про WPF Binding поймут о чем я, а кто не читал рекомендую прочитать, там описывается интерфейс INotifyPropertyChanged и динамическое обновление данных. |
Сообщ.
#2
,
|
|
|
Спасибо, Pit-Bul, за статью.
А теперь пара слов о том, почему НЕ надо переходить на WPF, в качестве дежурной ложки дёгтя. Кратко, осовываясь на собственном опыте. 1. Нужен дизайнер. У "чистого" программиста, как правило, больше шансов сделать плохой интерфейс на WPF, чем на WinForms. 2. Меньше сторонних контролов. Под WinForms разработаны тонны, тонны контролов всяких полезных, а под WPF - чуть поменьше. Ситуация выправляется со временем - причём, с платными контролами она выправляется быстрее, чем с бесплатными. 3. Требование .Net 3.5. Это ужастно, но он ещё неу всех есть. Реально массовый, увы, пока второй. Тоже со временем исправится, конечно. Не буду разжовывать эти пункты, но предлагаю читателю просто поразмыслить над ними. Сам я считаю, что плюсы WPF с лихвой перевешивают перечисленные (и забытые) мной минусы, но если задумаетесь о переходе - обязательно оцените, не являются ли эти минусы критичными в вашем проекте. |
Сообщ.
#3
,
|
|
|
прикрепляю забытые примеры
Прикреплённый файлWPF_Sample_F4.zip (45,25 Кбайт, скачиваний: 564) Прикреплённый файлWPF_Sample_F3.5.zip (71,51 Кбайт, скачиваний: 449) |
Сообщ.
#4
,
|
|
|
жду про паттерн!
|
Сообщ.
#5
,
|
|
|
Alexus, не подумай что развожу холивар, желания такого нет. Но сказать стоит.
Цитата Alexus @ 1. Нужен дизайнер. У "чистого" программиста, как правило, больше шансов сделать плохой интерфейс на WPF, чем на WinForms. Это все таки только на первый взгляд, потому как никто не мешает сделать такой же интерфейс как у WinForms на WPF если нет уверенности что оформление окажется не очень, но зато останутся преимущества в виде байндингов и прочей радости. Цитата Alexus @ 2. Меньше сторонних контролов. Под WinForms разработаны тонны, тонны контролов всяких полезных, а под WPF - чуть поменьше. Ситуация выправляется со временем - причём, с платными контролами она выправляется быстрее, чем с бесплатными. С 2008 года пишу на WPF еще ни разу не возникало желания воспользоваться сторонними контролами. Скажу даже более, недавно помогал товарищу привести проект на WinForms к более или менее нормальному виду, короче говоря затеяли большой рефакторинг. Так в энтом проекте куча DevExpress'овских гридов и прочего было полно. Скажу честно, после этого рефакторинга от DevExpress'овского грида просто воротит, ибо это монстр на все случаи жизни, не контрол а одно сплошное мучение, у него один функционал налагает ограничения на другой, да и чтобы что то реально функциональное на нем сделать придется попотеть. В WPF человеку который хтябы несколько месяцев имел с ним дело это же сделать получиться за какой то час, просто есть с кем сравнивать . Цитата Alexus @ 3. Требование .Net 3.5. Это ужастно, но он ещё неу всех есть. Реально массовый, увы, пока второй. Тоже со временем исправится, конечно. а вот с этим вынужден согласиться, сам пару раз сталкивался. И не смотря что WPF есть уже с 3.0 фреймворка, почемуто всегда хочется все делать на 4.0 даже если функционал того не требует. |
Сообщ.
#6
,
|
|
|
Цитата Alexus @ Кратко, осовываясь на собственном опыте. + на икспи текст криво отображается. нужно ставить какой-то там тюнинг на каждый клиент. |