依赖属性的困难
我的 Windows Phone Mango 应用程序上的依赖属性遇到了一些问题。以下是我想要动态更改其字体大小的两个控件:
<TextBlock Text="{Binding}" FontSize="{Binding ElementName=ParagraphItems, Path=DataContext.TextScale}" />
<local:HyperlinkTextBlock Text="{Binding}" FontSize="{Binding ElementName=ParagraphItems, Path=DataContext.TextScale}" />
TextBlock
工作正常,但 HyperlinkTextBlock
不行。 HyperlinkTextBlock
是我制作的一个类:
<UserControl
<!-- ... -->
>
<RichTextBox x:Name="LayoutRoot" TextWrapping="Wrap" FontSize="{Binding FontSize}">
<Paragraph x:Name="BaseParagraph" />
</RichTextBox>
</UserControl>
public partial class HyperlinkTextBlock : UserControl { /* ... */ }
我不确定需要在 HyperlinkTextBlock
中做什么才能使其能够接收 FontSize
在 XAML 中声明时的值。我尝试绑定到 HyperlinkTextBlock.xaml
中的属性,并在代码隐藏中更改属性时发出通知:(
public new double FontSize
{
get
{
return base.FontSize;
}
set
{
base.FontSize = value;
onPropChanged("FontSize");
}
}
它是 new
因为 UserControl
已经有a FontSize
属性 - 我不应该使用它吗?)
我还尝试创建一个全新的依赖属性:
public static readonly new DependencyProperty FontSizeProperty = DependencyProperty.RegisterAttached(
"FontSize",
typeof(double),
typeof(HyperlinkTextBlock),
new PropertyMetadata(20, new PropertyChangedCallback(onFontSizeChanged)));
public new double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
private static void onFontSizeChanged(DependencyObject dependObj, DependencyPropertyChangedEventArgs e)
{
((HyperlinkTextBlock)dependObj).LayoutRoot.FontSize = (double)e.NewValue;
}
同样,这不起作用。在运行时,它会给出错误:
System.ArgumentException was unhandled
Message=Default value type does not match type of property.
StackTrace:
at System.Windows.DependencyProperty.Register(Boolean fIsAttachedDP, String name, Type propertyType, Type ownerType, PropertyMetadata propertyMetadata, Boolean readOnly)
at System.Windows.DependencyProperty.RegisterAttached(String name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata)
at MyApp.Views.HyperlinkTextBlock..cctor()
at System.Reflection.RuntimeConstructorInfo.InternalInvoke(RuntimeConstructorInfo rtci, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
at System.Reflection.RuntimeConstructorInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
at MS.Internal.TypeProxy.<>c__DisplayClass30.<GetCreateObjectDelegate>b__2a()
at MS.Internal.TypeProxy.CreateInstance(UInt32 customTypeId)
at MS.Internal.XamlManagedRuntimeRPInvokes.CreateInstance(XamlTypeToken inXamlType, XamlQualifiedObject& newObject)
执行此操作的正确方法是什么?
更新:
如果我直接在HyperlinkTextBlock
上设置FontSize
:
<local:HyperlinkTextBlock Text="{Binding}" Margin="0,15" FontSize="33.0" />
<local:HyperlinkTextBlock Text="{Binding}" Margin="0,15" FontSize="40" />
并从HyperlinkTextBlock<中删除有关
FontSize
的任何内容/code> 本身:
<RichTextBox x:Name="LayoutRoot" TextWrapping="Wrap">
<Paragraph x:Name="BaseParagraph" />
</RichTextBox>
那么设置字体大小没有明显的效果。 (上面声明的两个文本块看起来相同。)
I'm having a bit of trouble with dependency properties on my Windows Phone Mango app. Here are two controls whose font size I'd like to change dynamically:
<TextBlock Text="{Binding}" FontSize="{Binding ElementName=ParagraphItems, Path=DataContext.TextScale}" />
<local:HyperlinkTextBlock Text="{Binding}" FontSize="{Binding ElementName=ParagraphItems, Path=DataContext.TextScale}" />
The TextBlock
works fine, but the HyperlinkTextBlock
does not. HyperlinkTextBlock
is a class I've made:
<UserControl
<!-- ... -->
>
<RichTextBox x:Name="LayoutRoot" TextWrapping="Wrap" FontSize="{Binding FontSize}">
<Paragraph x:Name="BaseParagraph" />
</RichTextBox>
</UserControl>
public partial class HyperlinkTextBlock : UserControl { /* ... */ }
I'm not sure what I need to do in HyperlinkTextBlock
to make it so it can receive FontSize
values when it is declared in XAML. I tried binding to the property in HyperlinkTextBlock.xaml
, and notifying when the property changes in code-behind:
public new double FontSize
{
get
{
return base.FontSize;
}
set
{
base.FontSize = value;
onPropChanged("FontSize");
}
}
(It's new
because UserControl
already has a FontSize
property - shouldn't I just be able to use that?)
I also tried creating an entirely new dependency property:
public static readonly new DependencyProperty FontSizeProperty = DependencyProperty.RegisterAttached(
"FontSize",
typeof(double),
typeof(HyperlinkTextBlock),
new PropertyMetadata(20, new PropertyChangedCallback(onFontSizeChanged)));
public new double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
private static void onFontSizeChanged(DependencyObject dependObj, DependencyPropertyChangedEventArgs e)
{
((HyperlinkTextBlock)dependObj).LayoutRoot.FontSize = (double)e.NewValue;
}
Similarly, this did not work. At runtime, it gives the error:
System.ArgumentException was unhandled
Message=Default value type does not match type of property.
StackTrace:
at System.Windows.DependencyProperty.Register(Boolean fIsAttachedDP, String name, Type propertyType, Type ownerType, PropertyMetadata propertyMetadata, Boolean readOnly)
at System.Windows.DependencyProperty.RegisterAttached(String name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata)
at MyApp.Views.HyperlinkTextBlock..cctor()
at System.Reflection.RuntimeConstructorInfo.InternalInvoke(RuntimeConstructorInfo rtci, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
at System.Reflection.RuntimeConstructorInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
at MS.Internal.TypeProxy.<>c__DisplayClass30.<GetCreateObjectDelegate>b__2a()
at MS.Internal.TypeProxy.CreateInstance(UInt32 customTypeId)
at MS.Internal.XamlManagedRuntimeRPInvokes.CreateInstance(XamlTypeToken inXamlType, XamlQualifiedObject& newObject)
What is the right way to go about doing this?
Update:
If I just set FontSize
directly on HyperlinkTextBlock
:
<local:HyperlinkTextBlock Text="{Binding}" Margin="0,15" FontSize="33.0" />
<local:HyperlinkTextBlock Text="{Binding}" Margin="0,15" FontSize="40" />
And remove anything about FontSize
from HyperlinkTextBlock
itself:
<RichTextBox x:Name="LayoutRoot" TextWrapping="Wrap">
<Paragraph x:Name="BaseParagraph" />
</RichTextBox>
Then there is no observable effect of setting the font size. (The two text blocks declared above appear identical.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
像这样更改依赖属性代码:
Int is not a double...
Change the dependency property code like this:
An int is not a double...
也许我没有得到什么,但为什么你将 FontSize 定义为附加属性?我会使用一个简单的依赖属性,为了避免任何混淆,我会给它一个与 FontSize 不同的名称(例如本例中的 HyperlinkFontSize),所以我会这样做:(
请注意,您不必提供当您传递事件处理程序时委托类型的名称。)
然后像这样进行绑定:
最后一件事:首先您尝试将 FontSize 实现为普通属性(带有更改通知)。这永远不会起作用,因为数据绑定的目标始终必须是依赖属性(尽管源可以是任何 CLR 属性,即使没有更改通知),如所述 此处。
更新:另一种方法是将 RichTextbox.FontSize 属性绑定到用户控件的 FontSize 属性,如下所示:
这样您就不需要额外的依赖属性,您可以简单地在 local:HyperlinkTextBlock 上设置 FontSize,例如你原来是这么做的。
Maybe I am not getting something, but why do you define FontSize as an attached property? I would go with a simple dependency property, and to avoid any confusion, I would give it a different name than FontSize (e. g. HyperlinkFontSize in this case), so I would do something like this:
(Note that you do not have to provide the name of the delegate type when you pass the event handler.)
And then do the binding like this:
And one last thing: at first you tried to implement the FontSize as an ordinary property (with change notification). That never should work, because the target of data binding always has to be a dependency property (although the source can be any CLR property, even without change notification), as stated here.
UPDATE: Another approach would be to bind the RichTextbox.FontSize property to the FontSize property of the user control, something like this:
That way you do not need the extra dependency property, and you can simply set the FontSize on the local:HyperlinkTextBlock like you originally did.
除非 Silverlight 5 和 Windows Phone 的 Silverlight 之间有什么不同,否则 FontSize 值应自动从其父级继承。您不需要创建任何依赖属性,也不需要在 UserControl 内进行任何绑定。我刚刚测试了以下内容(尽管在 PC 上)并且它有效:
这
就是结果:
更新:
确保删除/注释您添加的 FontSize 属性,否则我的示例将无法工作。
如果这仍然不适合您,并且由于 Silverlight 4 及更早版本没有 FindAncestor 标记扩展,也许命名您的 UserControl并使用它来绑定您的 RichTextBox。
Unless something's different between Silverlight 5 and Windows Phone's Silverlight, the FontSize value should automatically be inherited from its parent. You don't need to created any dependency properties, and you don't need to make any bindings inside your UserControl. I just tested the following (on PC though) and it worked:
and
This was the result:
Update:
Make sure to remove/comment the FontSize property you added, or my example won't work.
If that still doesn't work for you, and since Silverlight 4 and earlier doesn't have the FindAncestor mark-up extension, perhaps name your UserControl and use that to bind your RichTextBox to.