MVVM - كيفية إنشاء أعمدة في وقت التشغيل لـ XamDataGrid؟

StackOverflow https://stackoverflow.com/questions/3425972

  •  26-09-2019
  •  | 
  •  

سؤال

لا بد لي من إنشاء xamdatagrid يعرض كمية ديناميكية من الأعمدة لإطار زمني x إلى y. لذلك لا أعرف عدد السنوات التي سيختارها المستخدم لإنشاء هذه الأعمدة مقدمًا.

الآن معتاد داخل MVVM ، يمكنك فقط ملء البيانات من خلال أكبر عدد ممكن من الخصائص التي ستحتاج إليها في أعمدة داخل XamDataGrid الخاص بك ، وسيقوم الأخير بتدوينها تلقائيًا.

من الواضح أنني لم أتمكن من إنشاء خصائص داخل ViewModel في وقت التشغيل إلا إذا فعلت شيئًا مجنونًا مع التفكير.

وإلا كيف سأحقق هذا؟

هل يجب أن أقوم فقط بإنشاء حقول غير محدودة لـ DataGrid وملءها عبر الكود؟ أوافق على أنني لن أحتاج إلى ملزمة في هذه المرحلة ، لأن الشبكة لا تقرأ إلا ... فقط أفكر بصوت عالٍ.

هل هذا النهج على ما يرام دون انتهاك نمط MVVM؟ شكرًا

هل كانت مفيدة؟

المحلول

يمكنك استخدام الفهرسة:

في ViewModel الخاص بك:

public MyVariableCollection RowData
{
    get { return new MyVariableCollection(this); }
}

في MyVariableCollection: SomerOwViewModel المحمي ؛

public MyVariableCollection(SomeRowViewModel viewmodel)
{
    this.viewModel = viewmodel;
}

public object this[string name]
{
    get { return viewModel.GetRowColumnValue(name); }
}

لقد حاولت أن تبقيه موجزًا: لكن الفكرة هي أن لديك فصلًا جديدًا به فهرس محدد ، ثم يمكنك ربط مثل هذا:

{Binding Path=SomeRowViewModelInstance.RowData["ColumnName"]}

سيتم ربط مجموعة العمود على التحكم في شبكة البيانات - ويمكنك تعيين قالب عمود لكل عمود لربط العمود المعني ؛ لا تحتاج إلى استخدام سلسلة حرفية في الفهرس من هذا القبيل.

نأمل أن يوفر بعض الطعام للتفكير - أي أسئلة على هذا الطريق ، يرجى ترك تعليق.


تحرير لفكر إضافي: لقد استخدمت المحتويات ComponentModel مساحة الاسم لإنتاج العرف TypeDescriptor. إنه في عمق إلى حد ما ولكن يمكنك جعل كائن "يبدو" أن يكون له خصائص إضافية أو مخصصة. إنه أكثر تعقيدًا بكثير من طريقة الفهرس التي نشرتها أعلاه ، ولكن إذا تعثرت ، فهذا يستحق نظرة.

نصائح أخرى

واجهت مشكلة مماثلة لأن المستخدم كان قادرًا على تحديد أعمدة الشبكة في وقت التشغيل.

لقد كتبت عنصر تحكم يحتوي على DataGrid XAM وفضح خاصية تبعية مصدر البيانات لربط النموذج للشبكة (أي جدول بيانات).

في كل مرة يتغير فيها المصدر (يمكنك إضافة مستمعي الأحداث لـ PropertyChanged وحدث Grids FieldlayOutInitialization) تم إعادة تقديم الشبكة ديناميكيًا عن طريق مسح مصدر البيانات الخاص بها وإعادة تعيينه:

private void ReRenderGrid()
{
    XamDataGrid.FieldLayouts.Clear();
    XamDataGrid.ClearValue(DataPresenterBase.DataSourceProperty);
    XamDataGrid.DataSource = DataSource.Data.DefaultView;
}

يتم إعادة تكوين الأعمدة من قبل معالج الأحداث في الحدث التالي الذي أثاره XamDataGrid بعد إعادة تعيين DataSource Grids:

XamDataGrid.FieldLayoutInitializing += LayoutInitializing;

معالج:

private void LayoutInitializing(object sender, FieldLayoutInitializingEventArgs e)
{
    const string deletebuttonstyle = "DeleteButtonStyle";
    const string requiredinputvalue = "RequiredInputValue";
    const string optionalinputvalue = "OptionalInputValue";
    const string outputvalue = "OutputValue";

    var fieldLayout = e.FieldLayout;
    fieldLayout.Fields.Clear();

    AddFields(DataSource.InColumns, requiredinputvalue, fieldLayout);
    AddSplitter(fieldLayout);
    AddFields(DataSource.OptionalInColumns, optionalinputvalue, fieldLayout);
    AddSplitter(fieldLayout);
    AddFields(DataSource.OutColumns, outputvalue, fieldLayout);

    AddUnboundField(fieldLayout, string.Empty, GetStyle(deletebuttonstyle));
}

في حالتي ، احتوت مصدر البيانات على جميع الأعمدة التي قام المستخدم بتكوينها. مكالمات AddFields هذه الطريقة لكل إدخال قائمة:

private void AddField(string name, Style style, FieldLayout fieldLayout)
{
    var field = new Field {Name = name};
    field.Settings.LabelPresenterStyle = style;
    field.Settings.CellValuePresenterStyle = GetStyle("StandardCellValueStyle");
    fieldLayout.Fields.Add(field);
}

يتم تنفيذ AddSplitter و AddunboundField بطريقة مماثلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top