部落,
我构建了一个Silverlight自定义控件TextBubble,它是一个网格内的椭圆和文本块。我正在通过代码按需将这些文本气泡添加到画布对象。当我这样做时,TextBubble的属性被设置,但是当对象出现在画布上时不会反映出来。
如果我手动构建相同的结构并将其添加到画布canvas.Children.Add(grid),则此子项将正确显示。
使用TextBubble,文本和椭圆显示但直径和X,Y未应用,气泡显示在画布的左上角。
感谢您的帮助, -AM
有效的代码:
Grid g = new Grid();
g.SetValue(Canvas.TopProperty, 100.0);
g.SetValue(Canvas.LeftProperty, 100.0);
Ellipse e = new Ellipse();
e.Width = 50;
e.Height = 50;
e.Fill = new SolidColorBrush(Colors.Green);
g.Children.Add(e);
TextBlock t = new TextBlock();
t.Text = "TEST";
t.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
t.VerticalAlignment = System.Windows.VerticalAlignment.Center;
g.Children.Add(t);
this.canvas.Children.Add(g);
不符合的代码:
TextBubble bubble = new TextBubble();
bubble.Text = "TEST";
bubble.Diameter = 50;
bubble.Fill = new SolidColorBrush(Colors.Green);
bubble.X = 100;
bubble.Y = 100;
canvas.Children.Add(bubble);
TextBubble对象:
public class TextBubble : Control {
public TextBubble() {
this.DefaultStyleKey = typeof(TextBubble);
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(TextBubble),
new PropertyMetadata(new PropertyChangedCallback(OnTextChanged)));
public static readonly DependencyProperty DiameterProperty = DependencyProperty.Register(
"Diameter",
typeof(int),
typeof(TextBubble),
new PropertyMetadata(new PropertyChangedCallback(OnDiameterChanged)));
public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
"Fill",
typeof(Brush),
typeof(TextBubble),
new PropertyMetadata(new PropertyChangedCallback(OnFillChanged)));
public static readonly DependencyProperty XCoordProperty = DependencyProperty.Register(
"X",
typeof(double),
typeof(TextBubble),
new PropertyMetadata(new PropertyChangedCallback(OnXCoordChanged)));
public static readonly DependencyProperty YCoordProperty = DependencyProperty.Register(
"Y",
typeof(double),
typeof(TextBubble),
new PropertyMetadata(new PropertyChangedCallback(OnYCoordChanged)));
public string Text {
get { return (string)this.GetValue(TextProperty); }
set { base.SetValue(TextProperty, value); }
}
public int Diameter {
get { return (int)this.GetValue(DiameterProperty); }
set { base.SetValue(DiameterProperty, value); }
}
public Brush Fill {
get { return (Brush)this.GetValue(FillProperty); }
set { base.SetValue(FillProperty, value); }
}
public double X {
get { return (double)this.GetValue(XCoordProperty); }
set { base.SetValue(XCoordProperty, value); }
}
public double Y {
get { return (double)this.GetValue(YCoordProperty); }
set { base.SetValue(YCoordProperty, value); }
}
}
Generic.xml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:X4S.Controls" >
<Style TargetType="local:TextBubble">
<Setter Property="Text" Value="ABC" />
<Setter Property="Diameter" Value="50" />
<Setter Property="X" Value="100.0" />
<Setter Property="Y" Value="100.0" />
<Setter Property="Fill" Value="GhostWhite" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TextBubble">
<Grid x:Name="LayoutRoot" Canvas.Top="{TemplateBinding Y}" Canvas.Left="{TemplateBinding X}" >
<Ellipse Fill="{TemplateBinding Fill}" Width="{TemplateBinding Diameter}" Height="{TemplateBinding Diameter}"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Text}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
知道了!
当向画布子树添加新的自定义控件时,我们得到了包含grid-textblock-ellipse包的额外内容(TextBubble)。好吧,TextBubble对象从未设置过它的位置或大小。因此,即使文本和填充应用于内部控件,这些属性也不会受到TextBubble的位置或大小的影响。
一旦我们将相同的位置和大小属性应用于TextBubble本身 - 瞧它有效。
关键是: ((对照)canvas.GetDescendant())。GetDescendant()。的GetValue(Canvas.LeftProperty) 200.0
这表明网格确实是DID的位置设置 - 但其父级TextBubble却没有。
修复:
private static void OnDiameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
TextBubble textBubble = d as TextBubble;
textBubble.Width = (int)e.NewValue;
textBubble.Height = (int)e.NewValue;
}
private static void OnLeftChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
TextBubble textBubble = d as TextBubble;
textBubble.SetValue(Canvas.LeftProperty, e.NewValue);
}
private static void OnTopChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
TextBubble textBubble = d as TextBubble;
textBubble.SetValue(Canvas.TopProperty, e.NewValue);
}
可能有更好的方式(我会研究它),但这很有用。
答案 0 :(得分:0)
这是工作解决方案,我刚检查过它。你还有两个选择: 1.在构造函数中设置DataContext并使用常规绑定 2.不要设置DataContext并使用RelativeSource作为源(参见下面的XAML)
Canvas.Left&amp; amp;应该为canvas的直接子节点设置Canvas.Top,它是local:TextBubble。
<Style TargetType="local:TextBubble">
<Setter Property="Text" Value="ABC" />
<Setter Property="Diameter" Value="50" />
<Setter Property="Canvas.Top"
Value="{Binding Path=Y, RelativeSource={RelativeSource Self}}" />
<Setter Property="Canvas.Left"
Value="{Binding Path=X, RelativeSource={RelativeSource Self}}" />
<Setter Property="Fill" Value="GhostWhite" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TextBubble">
<Grid x:Name="LayoutRoot" >
<Ellipse Fill="{TemplateBinding Fill}" Width="{TemplateBinding Diameter}" Height="{TemplateBinding Diameter}"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Text}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>