ستونهای Dynamic در کنترل DataGrid توسط WPF (بخش دوم)
پنجشنبه 12 آذر 1394در اینجا قصد داریم مقاله قبلی در مورد ستونهای Dynamic در WPF را گسترش دهیم و درباره چگونگی اضافه کردن ستونهای داینامیک به DataGrid توضیح دهیم. در این بخش از مقاله تمرکز ما بر روی محدودیتهای معماری که در مقاله قبل نقض کردیم خواهد بود.
در اینجا قصد داریم مقاله قبلی در مورد ستونهای Dynamic در WPF را گسترش دهیم و درباره چگونگی اضافه کردن ستونهای داینامیک به DataGrid توضیح دهیم. در این بخش از مقاله تمرکز ما بر روی محدودیتهای معماری که در مقاله قبل نقض کردیم خواهد بود. راه حل بر اساس مقاله قبلی "ViewModel to View Interaction Request" خواهد بود. در اینجا از کتابخانه Small Application Framework استفاده میکنیم.
مقاله بعدی اعتبارسنجی داده های MVVM خواهد بود که چهارچوب برنامه را با یک کلاس پایه ای برای اعتبارسنجی داده ها گسترش می دهد و نشان می دهد چگونه مقادیری که در data grid وارد می شوند در مقابل قوانین تعیین شده اعتبارسنجی شوند.
همانطور که گفته شد در این مقاله قصد داریم در مورد حل محدودیتهای معماری است. در solution اصلی مجموعه ستونهای داینامیک را برای کم کردن پیچیدگی در MainViewModel قرار دادیم . به دلیل تصمیم این معماری ، باید کتابخانه PresentationFramework را در ViewModel اضافه کنیم. به این معنی است که بخشی از لایه رابط کاربری به درون لایه نمایش رخنه میکند و این نقض معماری لایه ای است.
دیاگرام زیر وضعیت قبلی را نشان می دهد که View Model یک مجموعه قابل مشاهده شامل ستونهای datagrid دارد. مجموعه ستونهای datagrid در موقعیت جدید حذف خواهند شد و PresentationCore و PresentationFramework و System.Xaml و منابع WindowsBase حذف خواهند شد.
کلاس ObjectTag نیز به لایه GUI منتقل خواهد شد. این کلاس برای یک ویژگی وابستگی با نام Tag استفاده خواهد شد. این ویژگی به نمونه ها اجازه پیوند داده شدن به ستونهای Grid متناظر را می دهد.
Small Application Framework
این کتابخانه توضیح می دهد که یک موقعیت مشابه در منطق ، در لایه View Model باید از لایه GUI جداسازی شود. در مقاله قبل توضیح داده شد که چگونه از باز کردن فایل و ذخیره Message box ها جلوگیری شود. در اینجا از همان مکانیزم برای مدیریت ستونهای داینامیک در datagrid استفاده میکنیم.
DataModel
DataModel همانند قبل است و تغییری نمیکند.
ViewModel
در سیستم جدید ، ستونها بوسیله grid control مدیریت می شوند. جهش از ستون بوسیله ViewModel از طریق اطلاعیه ای به لایه GUI درخواست داده می شود. در اینجا چهار نوع اطلاع رسانی داریم :
1. Add text column ، برای اضافه کردن ستون متن در grid استفاده می شود. (ستونهای نام و نام خانوادگی )
2. Add dynamic column ، برای اضافه کردن نقش جدید به grid استفاده می شود.
3. Cahnge dynamic column ، برای بروز رسانی ستون نقش استفاده می شود.
4.Delete dynamic column ، برای حذف کردن نقش از grid استفاده می شود.
کلاس DataColumnService شامل کلاس های درخواست تعاملی می شود که برای پاس دادن اطلاع رسانی ها از منطق به لایه GUI استفاده می شود..
MainViewModel شامل محتوای دیتابیس و منطق برای مقداردهی اولیه grid است. با رویداد های DataSet اشتراک پیدا میکند و رویداد های داده ای (اضافه کردن ، حذف کردن ، اعمال تغییرات) را با استفاده از اطلاع رسانی های درخواست ، به لایه GUI پاس می دهد.
MainWindow در لایه Application قابلیت مشابهی دارد و پیاده سازی ای از نسخه قبلی است. تفاوت آن با solution قبلی آن است که رفتار پیوست داده شده DataGridColumnsBehavior حذف شده است. این کلاس مسئول نظارت بر نقش های Data View بود و بروز رسانی grid زمانی که نقش ها تغییر می کردند.
نسخه جدید برای حل این مشکل از Trigger های کتابخانه های تعاملی استفاده میکند. در اینجا چهار Trigger موجود است. یکی برای وارد کردن یک ستون متنی و سه تا برای وارد کردن، حذف کردن و ایجاد تغییرات ستونهای نقش. هر Trigger پیاده سازی یک عمل را فراخوانی میکند، که کار واقعی را انجام می دهد. همه Action ها با پنجره اصلی در ارتباط هستند. هر عملی به پنجره اصلی دسترسی دارد و زیر کنترل آن است، پس می توان مجموعه ستونهای grid را تغییر داد.
یک Trigger اضافی یک رویداد است که با رویداد بارگذاری پنجره مشترک است و متد OnLoad از ViewModel فراخوانی میشود. این فراخوانی برای مقداردهی اولیه ستونهای Grid می شود.
منطق کاری
مقداردهی اولیه برنامه
برنامه بوسیله مسیریابی رویداد بارگذاری به ViewModel مقداردهی اولیه می شود و متد OnLoad را فراخوانی میکند. اولین کار مقداردهی استاندارد ستونها (نام و نام خانوادگی) است. دومین کاری که باید انجام شود اضافه کردن نقش های موجود است.
public void OnLoaded() { this.GenerateDefaultColumns(); this.InitializeRolesColumns(); } private void GenerateDefaultColumns() { this.AddTextColumn("First Name", "FirstName"); this.AddTextColumn("Last Name", "LastName"); } private void InitializeRolesColumns() { foreach (var role in this.databaseContext.DataSet.Role) { this.AddRoleColumn(role); } } private void AddTextColumn(string header, string binding) { var addTextColumnNotification = new AddTextColumnNotification { Header = header, Binding = binding }; DataColumnService.Instance.AddTextColumn.Raise(addTextColumnNotification); } private void AddRoleColumn(UserRoleDataSet.RoleRow role) { var notification = new AddDynamicColumnNotification { Role = role }; DataColumnService.Instance.AddDynamicColumn.Raise(notification); }
چهارچوب درخواست تعاملی، اجرای نمونه AddTextColumnAction را برای وارد کردن ستون های نام و نام خانوادگی نگهداری میکند.
public class AddTextColumnAction : TriggerActionBase<AddTextColumnNotification> { protected override void ExecuteAction() { var mainWindow = this.AssociatedObject as MainWindow; if (mainWindow != null) { mainWindow.DataGridUsers.Columns.Add( new DataGridTextColumn { Header = this.Notification.Header, Binding = new Binding(this.Notification.Binding) }); } } }
وارد کردن یک ستون Role
یک ستون role جدید از همان راه به عنوان یک ستون متنی اضافه شده است . فریم ورک ، کلاس AddDynamicColumnAction را فراخوانی میکند و یک اتصال اختصاصی ایجاد میکند که شامل بخش های زیر می شود:
. Converter ، یک مقدار مبدل . آن دسته از انتساب نقش به یک کاربر
. RelativeSource ، یک سلول datagrid شامل کنترل checkbox
. Path ، مسیر شیء ستون
. Mode ، دو راه اتصال برای بروزرسانی کنترل سلول grid
ستون DataGridCheckBoxColumn با سر تیتری از Role و اتصال و سبک عناصر ایجاد شده است. در پایان این ستون به لیست ستونهای grid اضافه شده است.
public class AddDynamicColumnAction : TriggerActionBase<AddDynamicColumnNotification> { protected override void ExecuteAction() { var resourceDictionary = ResourceDictionaryResolver.GetResourceDictionary("Styles.xaml"); var userRoleValueConverter = resourceDictionary["UserRoleValueConverter"] as IValueConverter; var checkBoxColumnStyle = resourceDictionary["CheckBoxColumnStyle"] as Style; var binding = new Binding { Converter = userRoleValueConverter, RelativeSource = new RelativeSource (RelativeSourceMode.FindAncestor, typeof(DataGridCell), 1), Path = new PropertyPath("."), Mode = BindingMode.TwoWay }; var dataGridCheckBoxColumn = new DataGridCheckBoxColumn { Header = this.Notification.Role.Name, Binding = binding, IsThreeState = false, CanUserSort = false, ElementStyle = checkBoxColumnStyle, }; ObjectTag.SetTag(dataGridCheckBoxColumn, this.Notification.Role); var mainWindow = this.AssociatedObject as MainWindow; if (mainWindow != null) { mainWindow.DataGridUsers.Columns.Add(dataGridCheckBoxColumn); } } }
انتساب نقش ها
اختصاص دادن نقش ها در UserRoleValueConverter انجام شد. که منطق آن در مقاله قبلی توضیح داده شد.
- WPF
- 2k بازدید
- 1 تشکر