Я не совсем уверен, если это то, что вы ищете, но это то, что я бы сделал
Во-первых: допустим, вы создали базовую таблицу данных и заполнили еес некоторыми значениями, такими как:
DataTable dt = new DataTable();
dt.Columns.Add("Key", typeof(int));
dt.Columns.Add("Material", typeof(string));
dt.Columns.Add("Price per Kilo", typeof(int));
dt.Rows.Add(1, "CobbleStone", 34);
dt.Rows.Add(2, "Wooden Planks", 12);
dt.Rows.Add(3, "Iron Ingots", 56);
, который выглядит так в отладчике:
Секунда: Получите некоторый VisualElement для отображения ваших данных.Я бы предложил использовать DataGrid
для.Итак, откройте свой MainWindows.xaml и добавьте DataGrid
к вашему Grid
с 3 DataGridTextColumns
следующим образом:
<DataGrid>
</DataGrid>
Поскольку мы хотим добавить свойства custiom в наши столбцы, мы должны добавитьAutoGenerateColumns="False"
в нашу DataGrid, если мы этого не сделаем, DataGrid автоматически сгенерирует свои столбцы на основе его ItemsSource.Поскольку теперь мы не получим автоматически сгенерированные столбцы, мы также должны добавить 3 столбца, напоминающих 3 столбца из нашей таблицы данных:
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Key" />
<DataGridTextColumn Header="Material" />
<DataGridTextColumn Header="Price per Kilo" />
</DataGrid.Columns>
</DataGrid>
Третий: Далее мы должны установить ItemsSource
наших DataGrid
.К сожалению, DataGrid
не может обработать DataTable
, поэтому сначала нужно преобразовать наш DataTable
во что-то, что DataGrid
может прочитать.Давайте сгенерируем для этого новый класс и назовем его MaterialModel , который выглядит следующим образом:
using System.ComponentModel;
using System.Runtime.CompilerServices;
class Model : INotifyPropertyChanged
{
private int m_Key;
public int Key
{
get
{
return m_Key;
}
set
{
m_Key = value;
OnPropertyChanged("Key");
}
}
private string m_Name;
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
OnPropertyChanged("Name");
}
}
private int m_Price;
public int Price
{
get
{
return m_Price;
}
set
{
m_Price = value;
OnPropertyChanged("Price");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Он имеет свойства и PropertyChangedEventHandler, который будет уведомлять ваш VisualElement при изменении свойства.
Четвертый: DataGrid
не принимает DataTables
, но принимает Lists
и ObserableCollections
.Используйте List
, если вы не хотите добавлять / изменять элементы во время выполнения.Я буду использовать ObserableCollection
, для работы которого нужно using System.Collections.ObjectModel;
.
Создайте свойство вашего списка и добавьте PropertyChangedEventHandler в MainWindow.
public partial class MainWindow : Window
{
private ObservableCollection<MaterialModel> m_MaterialList;
public ObservableCollection<MaterialModel> MaterialList
{
get
{
return m_MaterialList;
}
set
{
m_MaterialList = value;
OnPropertyChanged("MaterialList");
}
}
public MainWindow()
{
// [...]
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Следующим шагом будетчтобы преобразовать ваш DataTable в ObservableCollection
, так итерируйте ваш DataTable и конвертируйте каждую строку в одну из ваших моделей, например:
MaterialList = new ObservableCollection<MaterialModel>();
foreach(DataRow row in dt.Rows)
{
MaterialModel model = new MaterialModel
{
Key = int.Parse(row["Key"].ToString()),
Name = row["Material"].ToString(),
Price = int.Parse(row["Price per Kilo"].ToString()),
};
MaterialList.Add(model);
}
Fivth: Ваш список заполненМодели, следующим шагом будет рассказать вашему DataGrid
, как использовать ваш список.Сначала свяжите ваш список с ItemsSource
auf вашего DataGrid
, затем свяжите каждый DataGridTextColumn
с одним из свойств в вашей MaterialModel, например:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding MaterialList}">
<DataGrid.Columns>
<DataGridTextColumn Header="Key" Binding="{Binding Key}" />
<DataGridTextColumn Header="Material" Binding="{Binding Name}" />
<DataGridTextColumn Header="Price per Kilo" Binding="{Binding Price}" />
</DataGrid.Columns>
</DataGrid>
, и вы увидите DataGridworks:
Sixth: Последний шаг - фактически установить свойства ваших столбцов, что довольно просто, вашТребования будут выглядеть примерно так:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding MaterialList}">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Key" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Key}" Background="LightBlue"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Material" Binding="{Binding Name}" Width="300" />
<DataGridTextColumn Header="Price per Kilo" Binding="{Binding Price}" />
</DataGrid.Columns>
</DataGrid>
Я не нашел способа полностью создать DataGrid в Code, как вы хотели, но это все равно было бы плохой практикой.WPF предназначен для использования этого соединения между xaml и c #.
Если вы все равно хотите управлять свойствами столбца в c #, это будет правильным способом сделать это:
в вашем MainWindow.xaml.cs:
private double m_SecondColumnWidth;
public double SecondColumnWidth
{
get
{
return m_SecondColumnWidth;
}
set
{
m_SecondColumnWidth = value;
OnPropertyChanged("SecondColumnWidth");
}
}
public MainWindow()
{
SecondColumnWidth = 300;
}
XAML:
<!-- right beneath your Grid -->
<Grid.Resources>
<local:ViewModel x:Key="viewModel" />
</Grid.Resources>
<DataGridTextColumn Header="Material" Binding="{Binding Name}" Width="{Binding Source={StaticResource viewModel}, Path=SecondColumnWidth}" />
Это не совсем то, что вы хотели, но я надеюсь, что это поможет любым способом.