الربط لا يعمل عند استخدام عنصر التحكم المخصص في datagridtemplatecolumn


الربط لا يعمل عند استخدام التحكم المخصص في DataGridTemplateColumn

مسؤوليتي هي توفير عنصر تحكم يمكن استخدامه لتحديد عناصر متعددة من قائمة العناصر. العناصر هي علامات التصنيف. الكائن عبارة عن علامة. وله ثلاث خصائص (المعرف، الاسم، الوصف). هنا هو الكائن:

public class Tag : ObservableObject
{

  private int tagID;
  private string tagName;
  private string description;

  #region Properties
  public int TagID
  {
    get => tagID;
		set => SetProperty(ref tagID, value);
  }
  public string Name
  {
    get => tagName; 
	set => SetProperty(ref tagName, value);
  }
  public string Description
  {
    get => description; 
    set => SetProperty(ref description, value);
  }

  public Tag()
  { }
}

لقد قمت بإنشاء CustomControl يسمى TagSelect والذي يأخذ قائمة إلى خاصية تبعية تسمى SelectedTags. هذه هي العلامات التي يجب أن تظهر كما تم تحديدها، في البداية. ثم يقوم بعد ذلك بإنشاء مجموعة يمكن ملاحظتها من جميع العلامات الممكنة حتى يتمكن المستخدم من تحديد/إلغاء تحديد العلامات ذات الصلة. كما أنه يدير دقة قائمة SelectedTags الأصلية.

المشكلة التي أحتاج إلى المساعدة فيها هي هذه. عندما أختبر عنصر التحكم هذا بنفسه (تمامًا كعنصر في الشبكة) فإنه يعمل بدون مشكلة. ومع ذلك، كان الهدف الأصلي هو الاستخدام في DataGridColumn. عندما قمت بإنشاء DataGridTemplateColumn واستخدمت TagSelect Control في CellEditingTemplate، كان DP الخاص بـ SelectedTags فارغًا. أعلم أنها فارغة، لأنها تظهر (== خالية) داخل عنصر تحكم TagSelect عند نقطة توقف في أسلوب OnApplyTemplate.

لقد قمت ببناء مشروع صغير لإجراء اختبار عنصر التحكم هذا (TagBindExample). ويمكن الوصول إليه في
https://github.com/hardoverton/TagBindExample
بعض الأجزاء ذات الصلة من الحل:

فيما يلي كيفية استخدام عنصر التحكم عند الوقوف بمفرده في الشبكة:

<cc:TagSelect Width="175"
					SelectedTags="{Binding SomeTags}" />
<cc:TagSelect Width="175"
			  SelectedTags="{Binding OtherTags}" />

إليك كيفية تعريف DataGrid:

<DataGrid x:Name="TestGrid"
				Grid.Row="3"
				AutoGenerateColumns="False"
				ItemsSource="{Binding DataEntries}"
				Margin="80,0,80,0"
				Grid.ColumnSpan="2">
  <DataGrid.Columns>
    <DataGridTextColumn Width="40"
						Binding="{Binding ID}"
						Header="ID" />
    <DataGridTextColumn Width="200"
						Binding="{Binding Name}"
						Header="Name" />
    <DataGridTemplateColumn Width="175"
							Header="Tags">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
		  <TextBlock Text="{Binding TagString}" 
					Width="175"/>
		</DataTemplate>
	  </DataGridTemplateColumn.CellTemplate>
	  <DataGridTemplateColumn.CellEditingTemplate>
	    <DataTemplate>
		  <cc:TagSelect Width="175"
						SelectedTags="{Binding Tags}" />
		</DataTemplate>
	  </DataGridTemplateColumn.CellEditingTemplate>
	</DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

بيانات الاختبار الخاصة بـ DataGrid هي ObservableCollection DataEntries. وهنا بيانات الاختبار:

SomeTags List:
  3 - Boogie
  1 - Accord

OtherTags List:
  5 - Christmas Gifts
  6 - Data Science
  7 - Envoy

DataEntries Collection:
  0 - First Person, Tags:
        7 - Envoy
        2 - Bathroom Project
  1 - Second Person, Tags:
        5 - Christmas Gifts
        1 - Accord
        3 - Boogie
        8 - Fund-House
  2 - Third Person, Tags:
        5 - Christmas Gifts
        6 - Data Science
        7 - Envoy

فيما يلي تعريف DataEntry:

public class DataEntry : ObservableObject
{
	private int id;
	public int ID
    {
      get => id;
	  set => SetProperty(ref id, value);
    }

    private string? name;
    public string? Name
    {
	  get => name;
	  set => SetProperty(ref name, value);
    }

    private List<Tag> tags;
    public List<Tag> Tags
    {
			get => tags;
			set => SetProperty(ref tags, value);
    }

  private string tagString;
  public string TagString
  {
    get => tagString;
	set => SetProperty(ref tagString, value);	
  }

public DataEntry()
{
  tags = new List<Tag>();
}

فيما يلي تعريف خاصية التبعية SelectedTags في عنصر تحكم TagSelect:

ج #
public List<Tag> SelectedTags
	{
		get { return (List<Tag>)GetValue(SelectedTagsProperty); }
		set { SetValue(SelectedTagsProperty, value); }
	}
	public static readonly DependencyProperty SelectedTagsProperty =
			DependencyProperty.Register("SelectedTags", typeof(List<Tag>), typeof(TagSelect),
					new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

فقط عند استخدامه في DataGridTemplateColumn، يكون DP خاليًا. لا افهم لماذا. لسبب ما، لا يرى DataContext الخاص بـ DataGridRow. تكون بيانات الخلية الموجودة في السجل عبارة عن قائمة تمامًا كما هو الحال عند استخدامها بشكل مستقل. أعلم أنه فارغ لكل من سجلات الاختبار الثلاثة لأنني أرى ذلك في الموقع التالي لكل مثيل من عناصر التحكم. لا توجد حالات فشل ملزمة مبينة.:

ج #
public override void OnApplyTemplate()
{
  base.OnApplyTemplate();

  if (SelectedTags == null) SelectedTags = new List<Tag>();  <- break here
....
....

  FullTagSet = TagData.TagList;
  LoadSelections();
}

ما حاولت:

لقد جربت جميع الاقتراحات المعقولة التي وجدتها في البحث عن هذه المشكلة من خلال StackOverFlow وCodeProject وGitHub وأي مرجع آخر من محركات البحث.

لقد أضفت رابط TagString لاستخدامه في CellTemplate فقط لمعرفة ما إذا كنت قادرًا على الرجوع إلى DataGridRow بشكل صحيح. إنه يعمل كما هو متوقع.

ما الخطأ الذي أفعله في CellEditingTemplate والذي يجعلني أفشل في ذلك
الوصول إلى قائمة العلامات في كل سجل؟

هل أحاول القيام بشيء لا يسمح به DataGridTemplateColumn؟

إذا كان الأمر كذلك، فهل هناك نهج آخر للمتطلبات التي يجب أن أفكر فيها؟

コメント

タイトルとURLをコピーしました