如何编写此ItemsControl以便WPF使用绑定为输出网格生成列
下面的代码是一个主要工作的控件,可用于在具有两行的表中显示对象。第一行是标题行,第二行显示数据。正在显示的对象的属性可以定义为控件的项。每个项目在生成的表中显示为一列。我不想使用反射来实现此控件。这个问题不是关于反思 该控件有两个问题: 1.)它不是以“WPF形式”编写的(因为缺少更好的描述),因为我在代码中创建对象,而不是让绑定引擎来完成工作。我之所以用这种方式编码,是因为我不知道如何正确编码。注意,我正在为控件的ItemsPanel使用一个网格(应该是什么)。我希望使用网格,因为我希望输出是带有边框的表格形式。对于Items控件中的每个项,我需要绑定到网格第一行和第二行中的两个TextBlock。我还需要添加列,以便Items属性中的每个项都显示在一个新列中 2.)在BuildDataCell方法中创建的绑定不起作用。如果1.)已解决,则此问题最有可能得到解决。在不太可能的情况下,无法以WPF形式编写控件,如果能够使绑定正常工作,我希望使用它 下面的文章显示了我在研究这篇文章时遇到的几个StackOverflow问题。它要么没有回答我的问题,要么回答了我的问题,但我不知道为什么。 本文也是相关的,但我无法将其应用于此问题: InfoTable.cs如何编写此ItemsControl以便WPF使用绑定为输出网格生成列,wpf,binding,Wpf,Binding,下面的代码是一个主要工作的控件,可用于在具有两行的表中显示对象。第一行是标题行,第二行显示数据。正在显示的对象的属性可以定义为控件的项。每个项目在生成的表中显示为一列。我不想使用反射来实现此控件。这个问题不是关于反思 该控件有两个问题: 1.)它不是以“WPF形式”编写的(因为缺少更好的描述),因为我在代码中创建对象,而不是让绑定引擎来完成工作。我之所以用这种方式编码,是因为我不知道如何正确编码。注意,我正在为控件的ItemsPanel使用一个网格(应该是什么)。我希望使用网格,因为我希望输出是
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace InfoTableHost
{
public class InfoTableItem : DependencyObject
{
public String Header
{
get { return (String)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(String), typeof(InfoTableItem), new PropertyMetadata(String.Empty));
public string Data
{
get { return (string)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(string), typeof(InfoTableItem), new PropertyMetadata(String.Empty));
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberNameAttribute] string propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public class InfoTable : ItemsControl
{
public enum ColumnSizeModes
{
AutoFitGrowLast, // Shrink to fit except last column which expands to fill parent.
UniformWidth, // All Columns are the same width. Table expands to fill parent
AutoFit // Shrink to fit. Table does not expand to fill parent
}
public ColumnSizeModes ColumnSizeMode
{
get { return (ColumnSizeModes)GetValue(ColumnSizeModeProperty); }
set { SetValue(ColumnSizeModeProperty, value); }
}
public static readonly DependencyProperty ColumnSizeModeProperty =
DependencyProperty.Register("ColumnSizeMode", typeof(ColumnSizeModes), typeof(InfoTable), new PropertyMetadata(ColumnSizeModes.AutoFitGrowLast));
public Style HeaderCellStyle
{
get { return (Style)GetValue(HeaderCellStyleProperty); }
set { SetValue(HeaderCellStyleProperty, value); }
}
public static readonly DependencyProperty HeaderCellStyleProperty =
DependencyProperty.Register("HeaderCellStyle", typeof(Style), typeof(InfoTable), new PropertyMetadata(null));
public Style HeaderTextStyle
{
get { return (Style)GetValue(HeaderTextStyleProperty); }
set { SetValue(HeaderTextStyleProperty, value); }
}
public static readonly DependencyProperty HeaderTextStyleProperty =
DependencyProperty.Register("HeaderTextStyle", typeof(Style), typeof(InfoTable), new PropertyMetadata(null));
public Style DataCellStyle
{
get { return (Style)GetValue(DataCellStyleProperty); }
set { SetValue(DataCellStyleProperty, value); }
}
public static readonly DependencyProperty DataCellStyleProperty =
DependencyProperty.Register("DataCellStyle", typeof(Style), typeof(InfoTable), new PropertyMetadata(null));
public Style DataTextStyle
{
get { return (Style)GetValue(DataTextStyleProperty); }
set { SetValue(DataTextStyleProperty, value); }
}
public static readonly DependencyProperty DataTextStyleProperty =
DependencyProperty.Register("DataTextStyle", typeof(Style), typeof(InfoTable), new PropertyMetadata(null));
private bool isTemplateApplied;
private Grid RootGrid;
static InfoTable()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(InfoTable), new FrameworkPropertyMetadata(typeof(InfoTable)));
}
public InfoTable()
{
Loaded += InfoTable_Loaded;
}
void InfoTable_Loaded(object sender, RoutedEventArgs e)
{
if (!isTemplateApplied)
return;
Loaded -= InfoTable_Loaded;
RootGrid = (Grid)GetTemplateChild("root");
for (int i = 0; i < Items.Count; i++)
{
ColumnDefinition cd = new ColumnDefinition();
if (ColumnSizeMode == ColumnSizeModes.UniformWidth || (ColumnSizeMode == ColumnSizeModes.AutoFitGrowLast && i == Items.Count - 1))
cd.Width = new GridLength(1, GridUnitType.Star);
else
cd.Width = new GridLength(1, GridUnitType.Auto);
RootGrid.ColumnDefinitions.Add(cd);
}
RootGrid.RowDefinitions.Add(new RowDefinition());
RootGrid.RowDefinitions.Add(new RowDefinition());
foreach (InfoTableItem item in Items.Cast<InfoTableItem>())
{
int index = Items.IndexOf(item);
RootGrid.Children.Add(BuildHeaderCell(item, index));
RootGrid.Children.Add(BuildDataCell(item, index));
}
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (isTemplateApplied)
return;
isTemplateApplied = true;
}
private Border BuildHeaderCell(InfoTableItem item, int index)
{
Border b = new Border { Style = HeaderCellStyle };
TextBlock t = new TextBlock { Style = HeaderTextStyle, Text = item.Header };
b.SetValue(Grid.ColumnProperty, index);
b.Child = t;
return b;
}
private Border BuildDataCell(InfoTableItem item, int index)
{
Border b = new Border { Style = DataCellStyle };
TextBlock t = new TextBlock { Style = DataTextStyle };
Binding binding = new Binding { Source = Items[index], Path = new PropertyPath("Data"), UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
t.SetBinding(TextBlock.TextProperty, binding);
b.SetValue(Grid.ColumnProperty, index);
b.SetValue(Grid.RowProperty, 1);
b.Child = t;
return b;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用系统组件模型;
使用System.Runtime.CompilerServices;
命名空间InfoTableHost
{
公共类InfoTableItem:DependencyObject
{
公共字符串头
{
get{return(String)GetValue(HeaderProperty);}
set{SetValue(HeaderProperty,value);}
}
公共静态只读从属属性HeaderProperty=
DependencyProperty.Register(“标头”、typeof(字符串)、typeof(InfoTableItem)、new PropertyMetadata(String.Empty));
公共字符串数据
{
获取{return(string)GetValue(DataProperty);}
set{SetValue(DataProperty,value);}
}
公共静态只读DependencyProperty DataProperty=
Register(“Data”、typeof(string)、typeof(InfoTableItem)、newpropertyMetadata(string.Empty));
#区域INotifyPropertyChanged实现
公共事件属性更改事件处理程序属性更改;
public void RaisePropertyChanged([CallerMemberNameAttribute]字符串propertyName=”“)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
#端区
}
公共类信息表:ItemsControl
{
公共枚举列SizeModes
{
AutoFitGrowLast,//收缩以适应,但最后一列扩展以填充父列除外。
UniformWidth,//所有列的宽度都相同。表展开以填充父列
自动调整//收缩以调整。表不展开以填充父表
}
公共ColumnSizeModes ColumnSizeMode
{
获取{return(ColumnSizeModes)GetValue(ColumnSizeModeProperty);}
set{SetValue(ColumnSizeModeProperty,value);}
}
public static readonly dependencProperty ColumnSizeModeProperty=
DependencyProperty.Register(“ColumnSizeMode”、typeof(ColumnSizeModes)、typeof(InfoTable)、new PropertyMetadata(ColumnSizeModes.AutoFitGrowtlast));
公共风格头套风格
{
获取{return(Style)GetValue(HeaderCellStyleProperty);}
set{SetValue(HeaderCellStyleProperty,value);}
}
公共静态只读从属属性HeaderCellStyleProperty=
DependencyProperty.Register(“HeaderCellStyle”、typeof(Style)、typeof(InfoTable)、newpropertyMetadata(null));
公共样式标题文本样式
{
获取{return(Style)GetValue(HeaderTextStyleProperty);}
set{SetValue(HeaderTextStyleProperty,value);}
}
公共静态只读从属属性HeaderTextStyleProperty=
Register(“HeaderTextStyle”、typeof(Style)、typeof(InfoTable)、newpropertyMetadata(null));
公共样式数据单元样式
{
获取{return(Style)GetValue(DataCellStyleProperty);}
set{SetValue(DataCellStyleProperty,value);}
}
公共静态只读从属属性DataCellStyleProperty=
Register(“DataCellStyle”、typeof(Style)、typeof(InfoTable)、newpropertyMetadata(null));
公共样式DataTextStyle
{
get{return(Style)GetValue(DataTextStyleProperty);}
set{SetValue(DataTextStyleProperty,value);}
}
公共静态只读DependencyProperty DataTextStyleProperty=
Register(“DataTextStyle”、typeof(Style)、typeof(InfoTable)、newpropertyMetadata(null));
应用私有bool-istemplate;
私有网格RootGrid;
静态信息表()
{
OverrideMetadata(typeof(InfoTable),new FrameworkPropertyMetadata(typeof(InfoTable));
}
公共信息表()
{
加载+=信息表_加载;
}
已加载void InfoTable_(对象发送方,路由目标)
{
如果(!isTemplateApplied)
返回;
已加载-=信息表_已加载;
RootGrid=(Grid)GetTemplateChild(“根”);
对于(int i=0;i<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InfoTableHost">
<Style TargetType="{x:Type local:InfoTable}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HeaderCellStyle">
<Setter.Value>
<Style TargetType="Border">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="4" />
<Setter Property="Background" Value="Gray"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value=".5,.5,.5,.5"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="HeaderTextStyle">
<Setter.Value>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="DataCellStyle">
<Setter.Value>
<Style TargetType="Border">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="4" />
<Setter Property="Background" Value="DarkGray"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value=".5,0,.5,.5"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="DataTextStyle">
<Setter.Value>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:InfoTable}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalAlignment}">
<Grid VerticalAlignment="Top" x:Name="root" Margin="0">
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
<Window x:Class="InfoTableHost.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InfoTableHost"
Title="MainWindow" Height="350" Width="525" Padding="0">
<StackPanel DataContext="{Binding Observation}" >
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</StackPanel.Resources>
<local:InfoTable>
<local:InfoTableItem Header="Unbound Header" Data="Unbound Data"/>
<local:InfoTableItem Header="Observation Date" Data="{Binding ObSDate}"/>
<local:InfoTableItem Header="Close" Data="{Binding Close}"/>
</local:InfoTable>
<TextBlock>This TextBlock Binding Works: <TextBlock Text="{Binding ObsDate}" /></TextBlock>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace InfoTableHost
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public Observation Observation { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
Observation = new Observation { ObsDate = DateTime.Now, Close = 2201.55m };
}
}
public class Observation : INotifyPropertyChanged
{
private DateTime _ObsDate;
public DateTime ObsDate
{
get { return _ObsDate; }
set
{
if (_ObsDate != value)
{
_ObsDate = value;
RaisePropertyChanged();
}
}
}
private decimal _Close;
public decimal Close
{
get { return _Close; }
set
{
if (_Close != value)
{
_Close = value;
RaisePropertyChanged();
}
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberNameAttribute] string propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
public class InfoTableItem : FrameworkElement
{
...
}