自定义选择器控件在设置 ItemsSource 后不更新?
Custom Selector control does not update after ItemsSource has been set?
我已经根据 Selector 原语在 C# 中的 WPF 中组合了一个自定义控件:
public class PadControl : Selector
{
private const int padWidth = 28;
private const int padHeight = 18;
private const int padGap = 5;
private double _width;
private double _height;
static PadControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PadControl), new FrameworkPropertyMetadata(typeof(PadControl),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));
}
public PadControl()
{
}
protected override Size MeasureOverride(Size constraint)
{
_width = constraint.Width;
_height = constraint.Height;
return base.MeasureOverride(constraint);
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
var numHorz = _width / (padWidth + padGap);
var numVert = Math.Min(_height / (padHeight + padGap), 16);
var pen = new Pen(Brushes.Black, 1.0);
var brush = new SolidColorBrush(Color.FromRgb(192, 192, 192));
for(int bar = 0; bar < numHorz; bar++)
{
for(int track = 0; track < numVert; track++)
{
var rect = GetPadRect(bar, track);
dc.DrawRectangle(brush, pen, rect);
}
}
if (Items == null)
return;
brush = new SolidColorBrush(Colors.LightYellow);
var typeface = new Typeface("Tahoma");
foreach(PadViewModel item in Items)
{
var rect = GetPadRect(item.Bar, item.Track);
dc.DrawRectangle(brush, pen, rect);
var formatted = new FormattedText(item.Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12, Brushes.Black, 1.0)
{
MaxTextWidth = padWidth,
TextAlignment = TextAlignment.Center
};
dc.DrawText(formatted, GetPadPoint(item.Bar, item.Track));
}
}
private Rect GetPadRect(int bar, int track)
{
var rect = new Rect(bar * (padWidth + padGap) + padGap, track * (padHeight + padGap) + padGap, padWidth, padHeight);
return rect;
}
private Point GetPadPoint(int bar, int track)
{
var point = new Point(bar * (padWidth + padGap) + padGap, track * (padHeight + padGap) + padGap);
return point;
}
}
这会按照我的意愿进行绘制,但在我调整控件大小之前它不会绘制项目。
当控件第一次呈现时,它不会呈现任何项目,因为它是空的。项目是用这个间接填充的:
<controls:PadControl Grid.Column="0" Grid.Row="0" ItemsSource="{Binding Pads}"/>
问题是,在设置 ItemsSource 后我没有看到更新。所以问题是,我如何附加事件处理程序来捕获它?我是将它附加到 Items 还是附加到 ItemsSource?
答案是覆盖 OnItemsSourceChanged,如 Keith Stein 在上面的评论中所述。
我已经根据 Selector 原语在 C# 中的 WPF 中组合了一个自定义控件:
public class PadControl : Selector
{
private const int padWidth = 28;
private const int padHeight = 18;
private const int padGap = 5;
private double _width;
private double _height;
static PadControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PadControl), new FrameworkPropertyMetadata(typeof(PadControl),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));
}
public PadControl()
{
}
protected override Size MeasureOverride(Size constraint)
{
_width = constraint.Width;
_height = constraint.Height;
return base.MeasureOverride(constraint);
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
var numHorz = _width / (padWidth + padGap);
var numVert = Math.Min(_height / (padHeight + padGap), 16);
var pen = new Pen(Brushes.Black, 1.0);
var brush = new SolidColorBrush(Color.FromRgb(192, 192, 192));
for(int bar = 0; bar < numHorz; bar++)
{
for(int track = 0; track < numVert; track++)
{
var rect = GetPadRect(bar, track);
dc.DrawRectangle(brush, pen, rect);
}
}
if (Items == null)
return;
brush = new SolidColorBrush(Colors.LightYellow);
var typeface = new Typeface("Tahoma");
foreach(PadViewModel item in Items)
{
var rect = GetPadRect(item.Bar, item.Track);
dc.DrawRectangle(brush, pen, rect);
var formatted = new FormattedText(item.Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12, Brushes.Black, 1.0)
{
MaxTextWidth = padWidth,
TextAlignment = TextAlignment.Center
};
dc.DrawText(formatted, GetPadPoint(item.Bar, item.Track));
}
}
private Rect GetPadRect(int bar, int track)
{
var rect = new Rect(bar * (padWidth + padGap) + padGap, track * (padHeight + padGap) + padGap, padWidth, padHeight);
return rect;
}
private Point GetPadPoint(int bar, int track)
{
var point = new Point(bar * (padWidth + padGap) + padGap, track * (padHeight + padGap) + padGap);
return point;
}
}
这会按照我的意愿进行绘制,但在我调整控件大小之前它不会绘制项目。
当控件第一次呈现时,它不会呈现任何项目,因为它是空的。项目是用这个间接填充的:
<controls:PadControl Grid.Column="0" Grid.Row="0" ItemsSource="{Binding Pads}"/>
问题是,在设置 ItemsSource 后我没有看到更新。所以问题是,我如何附加事件处理程序来捕获它?我是将它附加到 Items 还是附加到 ItemsSource?
答案是覆盖 OnItemsSourceChanged,如 Keith Stein 在上面的评论中所述。