Динамическое привязка к значениям словаря в DataGrid Winui 3C#

Место общения программистов C#
Anonymous
Динамическое привязка к значениям словаря в DataGrid Winui 3

Сообщение Anonymous »

Я разрабатываю приложение Winui 3, которое отображает динамическую сетку (с использованием SFDatagrid от Syncfusion) сотрудников и их статусов SOP. У каждого сотрудника есть набор статусов SOP, хранящихся в словаре (ключ с нормированными именами SOP). Для каждого мастер -SOP соответствующий столбец сетки создается динамически, так что каждая ячейка отображает тик (✔), если у сотрудника есть такая SOP (и кнопка «Кликабельная», чтобы открыть файл) или крест (❌), если нет. Cross) плюс путь файла (если доступен) в свой свойство модели сотрудника. В противном случае отображение текстового блока, показывающего крест.
Проблема: < /p>
Даже если мой вывод отладки подтверждает, что, например, «Операции DFL Defillet Line Outfeed.doc» найден для работника (и его нормализованный ключ присутствует в словаре со статусом = «✔»), сетка по-прежнему показывает кросс. Also, I keep getting binding errors such as:
"BindingExpression path error: 'Status' property not found on 'MyNamespace.CasualEmployeeSkill'"
"BindingExpression path error: 'FilePath' property not found on 'MyNamespace.CasualEmployeeSkill'"
It appears that the binding isn’t reaching the Значение словаря (SopstatusEntry), но вместо этого пытается найти «статус» или «FilePath» на самом объекте сотрудника.

Код: Выделить всё

public class SOPStatusEntry
{
public string Status { get; set; } = "❌"; // Default value
public string FilePath { get; set; } = string.Empty; // Path to the file if available
}

public class CasualEmployeeSkill : INotifyPropertyChanged
{
public string EmployeeName { get; set; }
// Dictionary mapping normalized SOP names to their status entry
private Dictionary _sopStatus = new Dictionary();
public Dictionary SOPStatus
{
get => _sopStatus;
set { _sopStatus = value; OnPropertyChanged(nameof(SOPStatus)); }
}

public event PropertyChangedEventHandler PropertyChanged;
public void NotifySOPStatusChanged() => OnPropertyChanged(nameof(SOPStatus));

protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
< /code>
Динамическое создание столбцов в Code-behind: < /p>
// For each master SOP, add a column so that the cell’s DataContext is the dictionary value.
foreach (var sop in MasterSOPs)
{
string columnName = Normalize(sop.Name);
SkillMatrixGrid.Columns.Add(new Syncfusion.UI.Xaml.DataGrid.GridTemplateColumn
{
// IMPORTANT: Set MappingName to "SOPStatus[normalizedKey]"
MappingName = $"SOPStatus[{columnName}]",
HeaderText = sop.Name,
HeaderTemplate = (DataTemplate)this.Resources["SOPHeaderTemplate"],
CellTemplate = (DataTemplate)this.Resources["SOPCellTemplate"]
});
}
< /code>
Пример шаблона ячейки XAML: < /p>







< /code>
преобразователи (упрощенные примеры): < /p>
public class ButtonVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is string status)
return status == "✔" ? Visibility.Visible : Visibility.Collapsed;
return Visibility.Collapsed;
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}

public class TextVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is string status)
return status == "✔" ? Visibility.Collapsed : Visibility.Visible;
return Visibility.Visible;
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
< /code>
Ключевые точки: < /p>
Словарь Привязка:
Столочное сопоставление столбца должно быть установлено так, чтобы дата -образный данных ячейки - это значение словаря (экземпляр SopstatusEntry). Обратите внимание, что в приведенном выше коде мы используем:
mappingName = $ "sopstatus [{columnname}]"
(не добавляйте «.status» в mappingName.) Это работает, потому что DataContext для каждой ячейки является словарным значением от Sopstatus.  < /P>
Динамическая клавиша:
Нормализованное имя SOP (рассчитывается в коде-гибкости с помощью метода Normalize ()) используется в качестве ключа для каждой записи словаря. Этот ключ должен точно соответствовать определению динамического столбца и словарным заполненным для каждого сотрудника. Установив имя Mapping -Name без «.status», дата -обратный контекст ячейки становится правильным SopstatusEntry. (Например, если нормализованный ключ - «siteforkliftgeneraldoc», то связывание в шаблоне клетки должно быть разрешено с Sopstatusentry, соответствующим Sopstatus [»siteforkliftgeneraldoc"]). < /P>
мой вопрос:
Несмотря на то, что нанесение картирования правильного и подсчета Я до сих пор вижу такие ошибки, как «Ошибка пути BindingExpression:« Статус », не найденное в« CasualEmployeSkill ». Кажется, что привязка неправильно улавливает словарное значение. Кто -нибудь столкнулся с этой проблемой? Как я могу гарантировать, что динамическая сетка связывается с значением словаря (sopstatusentry), а не с родительским объектом сотрудника? Например, я попытался использовать привязки, такие как: < /p>


< /code>
Я ожидал, что сетка отобразит тик, если папка SOP сотрудника содержала файл, который слабо соответствует имени Master SOP, и в противном случае крест. Когда тик отображается, нажав на него, следует открыть файл. Несмотря на многочисленные попытки (и даже пробующие динамические ключи), я непрерывно получаю ошибки привязки, в которых кажется, что привязывающий двигатель ищет свойства «статус» и «FilePath» на объекте сотрудника, а не на запись в словаре (Sopstatus), связанные с каждой SOP. MappingName в коде-блудении), но ошибка сохраняется. Любая помощь в правильной связке с свойством динамического словаря и кнопкой ячейки видимой только тогда, когда статус SOP является тик (и для прохождения пути файла) будет очень оценена.  /> mainpage.xaml

    x:Class="Test.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:syncfusion="using:Syncfusion.UI.Xaml.DataGrid"
xmlns:local="using:Test">


















< /code>
mainpage.xaml.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Data;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Linq;
using System.Text.RegularExpressions;

namespace Test
{
public sealed partial class MainPage : Page
{
public ObservableCollection Employees { get; set; } = new ObservableCollection();
public List MasterSOPs { get; set; } = new List
{
"SOP1",
"SOP2"
};

public MainPage()
{
this.InitializeComponent();
LoadData();
}

private void LoadData()
{
// create a test employee.
var emp = new Employee { EmployeeName = "John Doe" };

// Populate the employee's dictionary for each master SOP.
foreach (var sop in MasterSOPs)
{
string key = Normalize(sop);
// For testing John Doe has SOP1 ("✔") and not SOP2 ("❌").
emp.SOPStatus[key] = new SOPStatusEntry
{
Status = sop == MasterSOPs.First() ? "✔" : "❌",
FilePath = sop == MasterSOPs.First() ? @"C:\Test\TestFile.doc" : string.Empty
};
}
Employees.Add(emp);

// Set up grid columns.
MyDataGrid.Columns.Clear();

// Add Employee Name column.
MyDataGrid.Columns.Add(new Syncfusion.UI.Xaml.DataGrid.GridTextColumn
{
MappingName = "EmployeeName",
HeaderText = "Employee Name",
Width = 200
});

// For each master SOP, add a column.
foreach (var sop in MasterSOPs)
{
string key = Normalize(sop);
MyDataGrid.Columns.Add(new Syncfusion.UI.Xaml.DataGrid.GridTemplateColumn
{
MappingName = $"SOPStatus[{key}]",  // MappingName to dictionary entry
HeaderText = sop,
CellTemplate = (DataTemplate)this.Resources["SOPCellTemplate"]
});
}

// Bind the collection to the grid.
MyDataGrid.ItemsSource = Employees;
}

private string Normalize(string input) =>
Regex.Replace(input, @"[^a-zA-Z0-9]", "").ToLower();
}

// Employee model.
public class Employee : INotifyPropertyChanged
{
public string EmployeeName { get; set;  }

// Dictionary mapping normalized SOP names to SOPStatusEntry.
private Dictionary _sopStatus = new Dictionary();
public Dictionary SOPStatus
{
get => _sopStatus;
set { _sopStatus = value; OnPropertyChanged(); }
}

public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

// Represents the status of an SOP.
public class SOPStatusEntry
{
public string Status { get; set; }  // "✔" if present, "❌" if missing
public string FilePath { get; set; }  // File path if available
}

// Converters to show/hide button or text depending on status.

public class ButtonVisibilityConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, string language)
{
return value is string status && status == "✔" ? Visibility.Visible : Visibility.Collapsed;
}

public object ConvertBack(object value, System.Type targetType, object parameter, string language)
{
throw new System.NotImplementedException();
}
}

public class TextVisibilityConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, string language)
{
return value is string status && status == "✔" ? Visibility.Collapsed : Visibility.Visible;
}

public object ConvertBack(object value, System.Type targetType, object parameter, string language)
{
throw new System.NotImplementedException();
}
}
}
Спасибо!

Подробнее здесь: https://stackoverflow.com/questions/794 ... 3-datagrid

Вернуться в «C#»