ستونهای Dynamic در کنترل DataGrid توسط WPF (بخش دوم)

در اینجا قصد داریم مقاله قبلی در مورد ستونهای Dynamic در WPF را گسترش دهیم و درباره چگونگی اضافه کردن ستونهای داینامیک به DataGrid توضیح دهیم. در این بخش از مقاله تمرکز ما بر روی محدودیتهای معماری که در مقاله قبل نقض کردیم خواهد بود.

ستونهای Dynamic در کنترل DataGrid توسط WPF (بخش دوم)

در اینجا قصد داریم مقاله قبلی در مورد ستونهای  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  انجام شد. که منطق آن در مقاله قبلی توضیح داده شد.

 

 

فایل های ضمیمه
دانلود نسخه ی PDF این مطلب