رفتن به مطلب

مقالات آموزشی و کاربردی در زمینه wpf


ارسال های توصیه شده

مقدمه:

در ادامه مقالات آموزشي WPF ، در اين مقاله، نحوه ساخت دکمه هاي سفارشي را در تکنولوژي WPF به صورت ساده و روان آموزش خواهم داد. براي فهم مطالب اين مقاله و استفاده و بهره وري از آن، نيازمند است تا خواننده با مفاهيم کلي WPF از جمله تعريف Brush ها، Style ها، نحوه ايجاد Resource ها و استفاده از آن ها، آشنايي داشته باشد. در اين مقاله از Microsoft Visual Studio.Net 2008 ، نسخه Professional به روز رساني شده با Service Pack1 استفاده شده است.

 

ايجاد پروژه:

در جهت سهولت ياد گيري کاربر، سعي کرده ام که به ساده ترين شکل ممکن، اين آموزش را در اختيار شما قرار دهم.

يک پروژه از نوع WPF Application ايجاد کنيد. نام دلخواهي را براي آن انتخاب نماييد. من در پروژه خودم آن را CustomButton ناميدم. در پنجره Solution Explorer بر روي Window1 راست کليلک نماييد و گزينه View Designer را کليک نماييد. مطمئن شويد که در قسمت کدهاي XAML مربوط به Window1 هستيد.

کد XAML مربوط به Window1 به صورت زير مي باشد:

 

 

 

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Window1" Height="300" Width="300">

قبل ازتعريف کد هاي زير را وارد نماييد.

 

 

کدهايي که براي ساخت دکمه خواهيم نوشت، در قسمت مربوط به Resource هاي Window1 قرار خواهند گرفت.(به نکته 1 آخر مقاله توجه نماييد.)

براي ساخت دکمه سفارشي يک Style جديد ايجاد خواهيم کرد، و سپس با تعريف خاصيت Template، شکل و حالت دلخواه خود را به دکمه خواهيم داد. اما قبل از ايجادStyle جديد، تعاريف مربوط به Brush ها را خواهيم آورد. در قسمت Resource ها، کد هاي زير را وارد نماييد.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

امي که براي هر آيتم تعيين گرديده است، به خوبي بيانگر عملکر آن آيتم نيز ميباشد. به عنوان مثال، آيتم DisabledForeColor ، رنگ مربوط به دکمه را، در زماني که دکمه، در حالت Disable مي باشد، مشخص مي نماييد. به آيتم ButtonRotater توجه نماييد. اين آيتم يک RotateTransform مي باشد، که در زماني که دکمه توسط کاربر فشرده مي شود، باعث چرخش 180 درجه اي Border مربوط به دکمه مي شود که اين امر باعث مي شود، فشرده شدن دکمه توسط کاربر به خوبي مشخص شود و هنگام فشرده شدن، ظاهر دکمه با حالت پيش فرض آن متفاوت باشد. (قبل از خواند ادامه مطالب به نکته شماره 2 آخر مقاله توجه کنيد.)

حال تعاريف مربوط به Style دکمه را در ادامه کد هاي فوق بنويسيد:

کد:

همانطور که در مقدمه مقاله آورده شد، خواننده بايد با مطالب تعريف Style ها، Trigger ها و ... آشنايي داشته باشد. به همين دليل در اين موارد توضيحي نخواهم داد. فقط به ذکر چند نکته در اکتفا خواهم کرد.

 

هنکام تعاريف Style ها معمولا يک Key براي آن در نظر خواهيم گرفت. که با دستور زير مشخص مي شود:

 

کد:

 

x:Key="[style key name]"

 

اما در Style فوق، من کليدي براي آن تعريف نکرده ام. اما تعريفي با عنوان

 

 

کد:

TargetType="{x:Type Button}"

را آورده ام. در واقع با اين عمل، Style مربوطه به تمامي دکمه هاي درون Window1 (و اگر Style در app.xaml تعريف شده باشد؛ به تمام دکمه هاي به کار رفته در همه Window هاي برنامه) اعمال خواهد شد و نيازي به مقدار دهي خاصيت Style دکمه ها، نخواهد بود.

 

براي کنترل رفتار دکمه، در حالت هاي مختلف، از Trigger ها و خواص مربوطه استفاده شده است. به عنوان مثال با تعريف Trigger زير

 

رنگ پس زمينه و پيش زمينه دکمه در حالتي که دکمه به صورت Disable ميباشد را به رنگ هاي متناسب و تعريف شده در بالاي Style نسبت مي دهد.

 

 

نکته 1:

چنانچه بخواهيد، از دکمه سفارشي، در همه Windows هاي برنامه استفاده نماييد، تعاريف مربوطه را در قسمت Resource ها فايل App.xaml قرار دهيد. علاوه براين مي توانيد يک Resource Dictionary ايجاد کرده و توسط دستور Merge Dictionaries ، آن را به Resource هاي برنامه اضافه نماييد. من در برنامه هاييم اغلب ازاين حالت استفاده مي کنم به اين دليل که قابليت Reusable بودن بالايي را به همراه خواهد داشت.

نکته 2:

مي توانيد، براي ايجاد Brush ها نيز يک Resource Dictionary در نظر بگيريد، تعاريف مربوط به Brush ها و عناصري را که در قسمت هاي مختلف ساخت کنترل هاي سفارشي شما، مشترک مي باشند را در آن نوشته و سپس آن را هنکام ايجاد کنترل هاي سفارشي، به آنها اضافه نماييد. اين عمل در هنگام تعريف و ساخت Style ها که در آن ها اغلي عناصر از رنگ هاي يکساني بهره مي برند، باعث صرفه جويي در وقت و کئ نويسي سريع و همچنين خوانا تر مي شود و از نوشتن کد هاي تکراري جلوگيري مي کند.

 

نکته3:

دقت کنيد که زماني که يک Style جديد براي يکي از عنصرهاي موجود در Visual Studio تعريف مي نماييد، تمامي کنترل آن عنصر در اختيار شما خواهد بود و در واقع مي توانيد عناصر و کنترل هاي جديد با ظاهر دلخواه خود را به وجود آوريد.

 

تبريک!!!

شما اولين کنترل سفارشي خود را با موفقيت ايجاد کرديد و مي توانيد از ان در برنامه هايتان استفاده نماييد.

شکل زير، نمونه هايي از دکمه ايجاد شده را در حالت هاي مختلف نشان مي دهد.

 

 

 

 

2u61sok.jpg

 

 

 

 

اميدوارم که اين مقاله نيز، کمکي در جهت ارتقاء سطح دانش شما درزمينه برنامه نويسي و استفاده از تکنولوژي WPF در برنامه هايتان نمايد.

خواهشمند است نظرات ،انتقادات و پيشنهادات خود را در رابطه با مقاله فوق از طريق ايميل با بنده در ميان گذاريد.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

  • Like 3
لینک به دیدگاه

مقدمه:

چند روز پیش دیدم که خیلیا دنبال Messagebox‌ فارسی و Customize‌شده هستند، گفتم یکی با WPF بنویسم تا دوستان با WPF‌و قابلیت هاش بیشتر آشنا بشن و ببینن چقدر لذت بخشه کار با WPF!

 

توضیحات:

این MessageBox هم میتونه فارسی باشه هم انگلیسی (پیش فرضش انگلیسی هست) و تقریبا همه قابلیت های Messagebox استاندارد رو داره + امکان تغییر Style‌همه قسمت هاش.

 

چند نمونه عکس ازش:

 

7eb0b62a2b.jpg

 

0a187b375c.jpg

 

برای تغییر اسکین :

 

 

WPFMessageBox.BackgroundBrush

WPFMessageBox.BorderBrush

WPFMessageBox.ButtonsStyle

WPFMessageBox.TitleTextStyle

WPFMessageBox.MessageTextStyle

 

قبل از Show کردن، با مقدار دهی به هر کدوم از ویژگی های بالا میتونین اسکین اونو تغییر بدید.

 

51fcddba31.jpg

 

برای فارسی کردن :

 

WPFMessageBox.IsPersian = true;

 

بعد Show میکنید.

 

6665737380.jpg

 

اینا هم دو تا style‌ مختلف که کد XAML‌ ش تو فایل ضمیمه هم موجوده:

 

5d024dcf2f.jpg

 

0057a75c13.jpg

  • Like 2
لینک به دیدگاه

مقدمه

 

یک نمونه برنامه ساده با استفاده از الگوی طراحی MVVM و Entity Framework در WPF برای کار با دیتابیس، که اعمال Select, Insert, Update و Delete را با استفاده از ساختار های الگوی MVVM انجام می دهد.

در صورتی که با الگوی MVVM آشنا نیستید مطالبی را که جناب آقای نصیری که در

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
در مورد MVVM قرار داده اند، مطالعه نمایید.

 

 

4.jpg?psid=1

 

 

توضیحات

 

شمای کلی برنامه بصورت زیر است که نمایانگر لایه های مختلف MVVM می باشد.

 

1.jpg?psid=1

 

لایه DataAccess:

شامل فایل دیتابیس است که یک جدول به نام Employee، دارای دو فیلد نام و ID می باشد. در این لایه می توان از انواع data source ها نظیر فایل های xml و ... نیز استفاده نمود.

البته توجه داشته باشید که چنین لایه ای در الگوی MVVM نامبرده نشده است اما برای شفافیت بیشتر کدنویسی معمولا برنامه نویسانی که با MVVM سر و کار دارند، چنین اقدامی می کنند!

 

لایه Model:

در این لایه باید مدلی از داده ای که در DataAccess وجود دارد، ایجاد کنیم. با استفاده از Entity Framework، یک Entity Data Model خواهیم داشت که به عنوان مدلی آماده از لایه DataAccess می توان از آن نام برد. زیرا کدهای مورد نیاز برای ایجاد کلاس های Model را بصورت خودکار تولید می کند.

 

 

 

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

001.[assembly: EdmSchemaAttribute()]

002.

003.namespace MVVM_EntityFramework.Model

004.{

005. #region Contexts

006.

007. ///

008. /// No Metadata Documentation available.

009. ///

010. public partial class EmployeeRepository : ObjectContext

011. {

012. #region Constructors

013.

014. ///

015. /// Initializes a new EmployeeRepository object using the connection string found in the 'EmployeeRepository' section of the application configuration file.

016. ///

017. public EmployeeRepository() : base("name=EmployeeRepository", "EmployeeRepository")

018. {

019. this.ContextOptions.LazyLoadingEnabled = true;

020. OnContextCreated();

021. }

022.

023. ///

024. /// Initialize a new EmployeeRepository object.

025. ///

026. public EmployeeRepository(string connectionString) : base(connectionString, "EmployeeRepository")

027. {

028. this.ContextOptions.LazyLoadingEnabled = true;

029. OnContextCreated();

030. }

031.

032. ///

033. /// Initialize a new EmployeeRepository object.

034. ///

035. public EmployeeRepository(EntityConnection connection) : base(connection, "EmployeeRepository")

036. {

037. this.ContextOptions.LazyLoadingEnabled = true;

038. OnContextCreated();

039. }

040.

041. #endregion

042.

043. #region Partial Methods

044.

045. partial void OnContextCreated();

046.

047. #endregion

048.

049. #region ObjectSet Properties

050.

051. ///

052. /// No Metadata Documentation available.

053. ///

054. public ObjectSet Employees

055. {

056. get

057. {

058. if ((_Employees == null))

059. {

060. _Employees = base.CreateObjectSet("Employees");

061. }

062. return _Employees;

063. }

064. }

065. private ObjectSet _Employees;

066.

067. #endregion

068. #region AddTo Methods

069.

070. ///

071. /// Deprecated Method for adding a new object to the Employees EntitySet. Consider using the .Add method of the associated ObjectSet property instead.

072. ///

073. public void AddToEmployees(Employee employee)

074. {

075. base.AddObject("Employees", employee);

076. }

077.

078. #endregion

079. }

080.

081.

082. #endregion

083.

084. #region Entities

085.

086. ///

087. /// No Metadata Documentation available.

088. ///

089. [EdmEntityTypeAttribute(NamespaceName="dbModel", Name="Employee")]

090. [serializable()]

091. [DataContractAttribute(IsReference=true)]

092. public partial class Employee : EntityObject

093. {

094. #region Factory Method

095.

096. ///

097. /// Create a new Employee object.

098. ///

099. /// Initial value of the id property.

100. public static Employee CreateEmployee(global::System.Int32 id)

101. {

102. Employee employee = new Employee();

103. employee.id = id;

104. return employee;

105. }

106.

107. #endregion

108. #region Primitive Properties

109.

110. ///

111. /// No Metadata Documentation available.

112. ///

113. [EdmScalarPropertyAttribute(EntityKeyProperty=false , IsNullable=true)]

114. [DataMemberAttribute()]

115. public global::System.String Name

116. {

117. get

118. {

119. return _Name;

120. }

121. set

122. {

123. OnNameChanging(value);

124. ReportPropertyChanging("Name");

125. _Name = StructuralObject.SetValidValue(value, true);

126. ReportPropertyChanged("Name");

127. OnNameChanged();

128. }

129. }

130. private global::System.String _Name;

131. partial void OnNameChanging(global::System.String value);

132. partial void OnNameChanged();

133.

134. ///

135. /// No Metadata Documentation available.

136. ///

137. [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]

138. [DataMemberAttribute()]

139. public global::System.Int32 id

140. {

141. get

142. {

143. return _id;

144. }

145. set

146. {

147. if (_id != value)

148. {

149. OnidChanging(value);

150. ReportPropertyChanging("id");

151. _id = StructuralObject.SetValidValue(value);

152. ReportPropertyChanged("id");

153. OnidChanged();

154. }

155. }

156. }

157. private global::System.Int32 _id;

158. partial void OnidChanging (global::System.Int32 value);

159. partial void OnidChanged();

160.

161. #endregion

162.

163. }

164.

165. #endregion

166.

167.}

 

 

لایه View:

 

برای View یک user control به نام EmployeeListView داریم که دارای یک DataGrid برای نمایش اطلاعات مشتریان، دو TextBox برای ورود اطلاعات و سه Button برای اعمال Insert و Update و Delete است. برای این کار از Command استفاده شده است.

برای کد XAML آن به این شکل است: (به Binding ها دقت کنید)

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

01.

02. xmlns="

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
"

03. xmlns:x="

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
"

04. xmlns:mc="

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
"

05. xmlns:d="

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
"

06. mc:Ignorable="d"

07. d:DesignHeight="300" d:DesignWidth="300">

08.

09.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

24.

25.

26.

27.

28.

29.

30.

31.

32.

33.

34.

35.

36.

37.

38.

39.

40.

41.

42.

43.

44.

45.

46.

47.

48.

49.

 

 

 

 

لایه ViewModel:

بطور کلی برای هر View یک ViewModel باید باشد تا منطق آن را تولید نماید.

در اینجا ما دو View داریم، user control و main wondow.

کار main window نمایش View های دیگر در داخل خود است به همین دلیل جزو لایه View محسوب نمی شود. اما برای کنترل منطق آن باید یک ViewModel برای آن نیز داشته باشیم تا بتوانیم قابلیت نمایش View های مختلف در داخل آن را بوجود بیاوریم.

کلاس ViewModelBase را نیز برای داشتن یک چارجوب کلی برای تمام ViewModel ایجاد می کنیم و همه ViewModel های موجود از آن ارث خواهند برد.

 

ViewModelBase

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

01.namespace MVVM_EntityFramework.ViewModel

02.{

03. public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable

04. {

05. protected ViewModelBase()

06. {

07. }

08.

09. public event PropertyChangedEventHandler PropertyChanged;

10.

11. protected virtual void OnPropertyChanged(string propertyName)

12. {

13. PropertyChangedEventHandler handler = this.PropertyChanged;

14. if (handler != null)

15. {

16. var e = new PropertyChangedEventArgs(propertyName);

17. handler(this, e);

18. }

19. }

20.

21. public void Dispose()

22. {

23. this.OnDispose();

24. }

25.

26. protected virtual void OnDispose()

27. {

28. }

29. }

30.}

 

 

 

 

MainWindowViewModel

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

01.namespace MVVM_EntityFramework.ViewModel

02.{

03. public class MainWindowViewModel : ViewModelBase

04. {

05. readonly EmployeeRepository _employeeRepository;

06.

07. ObservableCollection _viewModels;

08.

09. public MainWindowViewModel()

10. {

11. _employeeRepository = new EmployeeRepository();

12. EmployeeListViewModel viewModel = new EmployeeListViewModel(_employeeRepository);

13. this.ViewModels.Add(viewModel);

14. }

15.

16. public ObservableCollection ViewModels

17. {

18. get

19. {

20. if (_viewModels == null)

21. {

22. _viewModels = new ObservableCollection();

23. }

24. return _viewModels;

25. }

26. }

27. }

28.}

 

 

 

 

 

EmployeeListViewModel

به تعاریف Command ها توجه نمایید.

 

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

001.namespace MVVM_EntityFramework.ViewModel

002.{

003. class EmployeeListViewModel : ViewModelBase

004. {

005.

006.

007. readonly EmployeeRepository _employeeRepository;

008.

009. RelayCommand _insertCommand;

010. RelayCommand _updateCommand;

011. RelayCommand _deleteCommand;

012.

013. public Employee NewEmployee { get; set; }

014.

015. public ObservableCollection AllEmployees

016. {

017. get;

018. private set;

019. }

020.

021. public EmployeeListViewModel(EmployeeRepository employeeRepository)

022. {

023. if (NewEmployee == null)

024. NewEmployee = new Employee();

025. if (employeeRepository == null)

026. {

027. throw new ArgumentNullException("employeeRepository");

028. }

029. _employeeRepository = employeeRepository;

030. var tmp = from o in employeeRepository.Employees

031.

032. select o;

033. this.AllEmployees = new ObservableCollection(tmp.ToList());

034. }

035.

036. protected override void OnDispose()

037. {

038. this.AllEmployees.Clear();

039. }

040.

041.

042.

043. public ICommand InsertCommand

044. {

045. get

046. {

047. if (_insertCommand == null)

048. {

049. _insertCommand = new RelayCommand(param => this.InsertCommandExecute(), param => this.InsertCommandCanExecute);

050. }

051. return _insertCommand;

052. }

053. }

054.

055. public ICommand UpdateCommand

056. {

057. get

058. {

059. if (_updateCommand == null)

060. {

061. _updateCommand = new RelayCommand(param => this.UpdateCommandExecute(), param => this.UpdateCommandCanExecute);

062. }

063. return _updateCommand;

064. }

065. }

066.

067. public ICommand DeleteCommand

068. {

069. get

070. {

071. if (_deleteCommand == null)

072. {

073. _deleteCommand = new RelayCommand(param => this.DeleteCommandExecute(), param => this.DeleteCommandCanExecute);

074. }

075. return _deleteCommand;

076. }

077. }

078.

079. void InsertCommandExecute()

080. {

081. Employee emp = Employee.CreateEmployee(NewEmployee.id);

082. emp.Name = NewEmployee.Name;

083. _employeeRepository.Employees.AddObject(emp);

084. _employeeRepository.SaveChanges();

085. var tmp = from o in _employeeRepository.Employees

086.

087. select o;

088. this.AllEmployees = new ObservableCollection(tmp.ToList());

089. OnPropertyChanged("AllEmployees");

090. }

091.

092.

093. bool InsertCommandCanExecute

094. {

095. get

096. {

097. var tmp = from o in _employeeRepository.Employees

098. where o.id == NewEmployee.id

099. select o;

100. if (tmp != null && tmp.Count() > 0)

101. {

102. return false;

103. }

104. return true;

105. }

106. }

107.

108. void UpdateCommandExecute()

109. {

110. var tmp = from o in _employeeRepository.Employees

111. where o.id == NewEmployee.id

112. select o;

113. tmp.First().Name = NewEmployee.Name;

114. _employeeRepository.SaveChanges();

115. var tmp2 = from o in _employeeRepository.Employees

116. select o;

117. this.AllEmployees = new ObservableCollection(tmp2.ToList());

118. OnPropertyChanged("AllEmployees");

119. }

120.

121.

122. bool UpdateCommandCanExecute

123. {

124. get

125. {

126. var tmp = from o in _employeeRepository.Employees

127. where o.id == NewEmployee.id

128. select o;

129. if (tmp != null && tmp.Count() > 0)

130. {

131. return true;

132. }

133. return false;

134. }

135. }

136.

137. void DeleteCommandExecute()

138. {

139. var tmp = _employeeRepository.Employees.Single(o => o.id == NewEmployee.id);

140. _employeeRepository.Employees.DeleteObject(tmp);

141. _employeeRepository.SaveChanges();

142. var tmp2 = from o in _employeeRepository.Employees

143. select o;

144. this.AllEmployees = new ObservableCollection(tmp2.ToList());

145. OnPropertyChanged("AllEmployees");

146. }

147.

148.

149. bool DeleteCommandCanExecute

150. {

151. get

152. {

153. var tmp = from o in _employeeRepository.Employees

154. where o.id == NewEmployee.id

155. select o;

156. if (tmp != null && tmp.Count() > 0)

157. {

158. return true;

159. }

160. return false;

161. }

162. }

163. }

164.}

 

 

 

 

نکته :

فایل App.cs را بصورت زیر تغییر می دهیم تا در زمان لود برنامه، محتوی main window را مشخص کنیم. main window قابلیت نمایش هر ViewModel ای را دارد و هر ViewModel دارای یک View است که در نهایت آن View دز main window نمایش داده می شود.

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

01.namespace MVVM_EntityFramework

02.{

03. ///

04. /// Interaction logic for App.xaml

05. ///

06. public partial class App : Application

07. {

08. protected override void OnStartup(StartupEventArgs e)

09. {

10. base.OnStartup(e);

11. MainWindow window = new MainWindow();

12. var viewModel = new MainWindowViewModel();

13. window.DataContext = viewModel;

14. window.Show();

15. }

16.

17. }

18.}

 

 

 

 

دقت کنید که در بخش XAML کلاس App قسمت مربوط به StaurtupUri را حذف کنید.

 

و در آخر، کد XAML مربوط به MainWindow به شکل زیر خواهد بود:

(به Resource های آن و Binding مربوط به ItemsSource دقت نمایید)

 

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

01.

02. xmlns="

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
"

03. xmlns:x="

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
"

04. xmlns:vm="clr-namespace:MVVM_EntityFramework.ViewModel"

05. xmlns:vw="clr-namespace:MVVM_EntityFramework.View"

06. Title="MainWindow" Height="350" Width="525" Background="#FFBCB4B4">

07.

08.

09.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

24.

 

 

 

 

نتیجه:

MainWindow را به گونه ای طراحی کردیم که قادر به نمایش دادن ViewModel های مختلف باشد. هر ViewModel نیز یک منطق است که داده ها را از Model (یا DataAccess) گرفته و با استفاده از یک View، در MainWindow نمایش می دهد. توجه داشته باشید که هیچ کدام از فایل های XAML، دارای کدنویسی در Code-behind خود نیستند (به جز کد های پیش فرض خودشان) و این امر سبب می شود به راحتی بتوانید View های خود را به دلخواه و بدون نگرانی از به هم ریختن کدها تغییر دهید. تنها کار لازم، اعمال Binding ها در کد XAML است!

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

  • Like 2
لینک به دیدگاه

در بعضی برنامه های بنا به دلایلی برای توسعه دهنده هیچ اهمیتی ندارد که کاربر چند نمونه از برنامه را اجرا کند ولی اگر زمانی اجرای برنامه محدود بشود (به یک فرم )،برای این جور برنامه ها 3 نوع سناریو وجود دارد که به شرح آنها می پردازیم.

اولین سناریو را می توان نرافزاری در نظر گرفت که فقط یک نمونه از آن اجرا می شود (فقط یک پنجره اصلی) و می تواند پارامتر های را در هنگام اجرا بپذیرد به طور مثال برنامه ی مثل ویندوز مدیا پلیر و سناریو دیگر این است که در واقع از نرم افزار فقط یک نمونه اجرا می شود ولی دارای تعدادی پنجره مختلف است (Document Base) از این برنامه ها می توان MS Word رو مثال زد که کاربر شاید فکر بکند چند نمونه از برنامه را اجرا کرده در صورتی که فقط یک نمونه از برنامه اجرا شده و پنجره های مختلف را مدیریت می کند که از افزوده شدن سربار اضافی به سیستم جلوگیری می کند و سناریو آخری که می توان در نظر داشت برنامه ای که فقط یک نمونه از ان اجرا می شود (فقط یک پنجره اصلی) و هیچ پارامتر ورودی نمی پذیرد.البته سناریوهای دیگری را نیز می توان نام برد ولی ما به همین سه سناریو اکتفا می کنیم

 

 

برای پیاده سازی این قبیل نرم افزار ها راه حل های زیادی وجود دارد که هر کدام کم وبیش این قابلیت را به ما می دهند ولی ما قصد بررسی روشی رو داریم که در آن بتوان هر سه سناریو را پیاده سازی کرد

 

 

مثلا برای این منظور از Mutex استفاده می کنند که در آن نمی توان سناریویی اول و دوم را پیاده سازی کرد و یا پردازش ها بررسی می کنند که باز هم شامل سناریویی 1و2 نمی شود

 

کد:

 

( 1 )

 

با ارائه شدن WPF توسط مایکرسافت برای این منظور در C#‎‎ هیچ تمهیداتی پیش بینی نشده بود ولی تیم توسعه VB.NET این امکان را فراهم کرده بودند که ما نیز قصد استفاده از آن را در C#‎‎ داریم

 

در VB.NET در فضای نام کلاسی وجود دارد به نام

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
که این امکان را برای ما فراهم می کندو ما با مشتق کردن کلاسی از این کلاس می توانیم موفق به پیاده سازی هر سه سناریو بشویم.

این کلاس سه عضو را پیاده سازی می کند که از آنها برای این منظور استفاده می کنیم

 

 

  • برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
    : یک خصیصه است و مشخص می کند که آیا از این برنامه فقط یک نمونه اجرا بشود یا نه؟ که ما آن را در سازنده کلاس با true مقدار دهی می کنیم.
  • برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
    : این رویداد زمانی رخ می دهد که اولین نمونه از برنامه در حال ساخته شدن است و می توانیم به آرگومان های ورودی دسترسی داشته باشیم( StartupEventArgs ).
  • برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
    : همانطور که از نامش پیداست این زمانی رخ می دهد که نمونه دیگری از برنامه در حال ساخته شدن باشد.در این رویداد نیز می توان به آرگومان های ورودی دسترسی داشته باشیم ( StartupNextInstanceEventArgs )

خوب برای این که بتوانید به این کلاس دسترسی پیدا کنید با ید یک ارجاع به اسمبلی Microsoft.VisuaBasic.dllدر پروژه داشته باشید.

 

در اینجا ما سناریوی دوم را بررسی می کنیم که مشکلترین آنهاست و توسعه دهندگان اکثرا با پیاده سازی آن مشکل دارند

ابتدا یک کلاس را از WindowsFormsApplicationBase مشتق می کنیم و پیاده سازی زیر را انجام می دهیم

 

کد :

 

( 2 )

 

این کلاس یک نمونه از شی Application مورد نظر ما را نگهداری می کند (App) و در رویداد OnStartup یک نمونه از شی Application ساخته می شود و در رویداد OnStartNextInstance پنجره اصلی برنامه با نام MyWindow فعال می شود و سپس آرگومان های ورودی پردازش می شوند .توجه کنید که این قاعده کلی است و اگر این قسمت را متوجه شوید 70% راه را طی نموده اید.

حال ما قسمت کد نویسی شی Application را بررسی می کنیم (نه کد XAML)

 

 

کد :

 

( 3 )

 

در این کلاس تابع ProcessArgs آرگومان های ورودی را گرفته و تجزیه می کند سپس اطلاعات را به تابعی با همین نام در شئ MyWindow تحویل می دهد (ورودی ها در ادامه بررسی خواهند شد)

 

 

حال نگاهی به پیاده سازی MyWindow می اندازیم

 

کد :

 

( 4 )

 

در این پنجره که به عنوان پنجره اصلی برنامه است شما می بایست آرگومان های ورودی را بررسی (Parse) کنید و نمایش صحیحی رو بسته به برنامه در اختیار کاربر قرار دهید که ما در اینجا وقت به نمایش آرگومان های ورودی بسنده می کنیم.

ورودی اول آرگومتن های ورودی است و ورودی دوم مشخص می کند که آیا نمونه اول و اصلی است یا نمونه دیگر (اجرای اول با دیگر)

 

توجه کنید که تا این جا این راه حل برای یک Build از برنامه کار می کند واگر بخواهید که برای انواع Build های نرم افزار در یک سیستم جواب بدهد باید در فایل Assembly.cs پروژه خود یک اتریبیوت به نام GuidAttribute را بیفزایید چون اگر Guidرو مقداردهی نکنید دات نت در هر بار Build یک Guid به آن اختصاص می دهدو در Build های مختلف برنامه نمی توانید یک فرم واحد داشته باشید.

 

 

کد:

 

( 4 )

 

حاصل برنامه بالا با توجه به ورودی های مختلف در تصویر زیر مشخص است

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

منابع : من اول این نکته رو در کتاب

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
خوندم بعد از
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
تکمیلش کردم.

 

فایل پروژه را می توانید از {

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
} دریافت کنید.

 

 

 

کدها به پیوست میباشد .

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

  • Like 1
لینک به دیدگاه
×
×
  • اضافه کردن...