我是一名经验丰富的C#开发人员,但是一名WPF新手。基本问题(我认为)我无法通过网络搜索找到答案。这是简化的用例...
我想在WPF TextBlock中显示一个字符串。所以我在我的XAML控件的代码隐藏中编写了一些C#代码......
public class MyCoolControl : UserControl
{
public void InitializeMyCoolControl()
{
this.DataContext = "SomeStringOnlyAvailableAtRuntime"; // Perhaps from a database or something...
}
}
我设置了这样的XAML:
<UserControl ... snip...>
<!-- Bind the textblock to whatever's in the DataContext -->
<TextBlock Text="{Binding}"></TextBlock>
</UserControl>
效果很好,我可以在执行应用程序时看到值“SomeStringOnlyAvailableAtRuntime”。但是,我在使用Visual Studio 2008的XAML Designer时没有在设计时看到任何内容。
如何在设计时查看文本块的占位符值(任何内容)?
谢谢!
-Mike
答案 0 :(得分:19)
在设计用户控件时,我经常在绑定上使用FallbackValue
来查看内容。例如:
<TextBlock Text={Binding Path=AverageValue, FallbackValue=99.99} />
但是,由于FallbackValue
不仅仅是在设计时应用,如果您想在运行时出于其他原因使用FallbackValue
,这可能不合适。
答案 1 :(得分:2)
在您的示例中,您可能需要使用TargetNullValue
,而不是FallbackValue
,因为绑定表达式可能是null
,因为DataContext
是null
at设计时间。
FallBackValue
不存在,则使用 Path
,但由于没有指定路径,我认为DataContext
将被评估为null
}。
<UserControl ... snip...>
<!-- Bind the textblock to whatever's in the DataContext -->
<TextBlock Text="{Binding TargetNullValue=Nothing to see}"></TextBlock>
</UserControl>
另请注意,需要.NET Framework 3.5 SP1,因为在SP1中添加了这两个附加属性。
答案 2 :(得分:0)
我不知道如何使用Visual Studio的编辑器执行此操作,但您可以使用Expression Blend执行此操作。
Here's以及描述如何实现这一目标的文章。
我希望MS将Blend和Visual Studio的功能合并在一起,因为有一个包做一件事而另一件有点傻。特别是当他们来自同一家公司时。
答案 3 :(得分:0)
在这种情况下,让MultiValueConverter或ViewModel对象处理对象加载并为您更新依赖项属性不是最佳选择吗?
答案 4 :(得分:0)
TargetNullValue
和 FallbackValue
在运行时都有函数,所以它们不是很好的占位符选择。
TargetNullValue
:如果目标属性值等于TargetNullValue
,源属性将被设置为null
,如果源属性是null
,目标属性将被设置为TargetNullValue
。
FallbackValue
:如果Binding
的源为null
或者源属性转换为目标属性失败,则目标属性将设置为FallbackValue
。
您可以创建一个自定义的 MarkupExtension 来在设计器中显示占位符,并在运行时进行正常绑定
我的代码:
//Coding by Squirrel Downy(Flithor)
public class PlaceHolderBinding : MarkupExtension
{
/// <summary>
/// Show placeholder in designer, if null than ignore it
/// </summary>
public object PlaceHolder { get; set; }
/// <summary>
/// Binding works in runtime
/// </summary>
public BindingBase Binding { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
//if no binding
if (Binding == null) throw new ArgumentNullException("Binding");
//get target info
var target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (target == null) throw new InvalidOperationException("Only support as Binding");
//get target object and check is DependencyObject
if (!(target.TargetObject is DependencyObject targetObject))
throw new InvalidOperationException("Only support on DependencyObject");
//if target in designer, return placeholder
if (DesignerProperties.GetIsInDesignMode(targetObject))
return PlaceHolder;
//get target property and check is DependencyProperty
if (!(target.TargetProperty is DependencyProperty targetProp))
throw new InvalidOperationException("Only support on DependencyProperty");
//set binding and return binding provide value
BindingOperations.SetBinding(targetObject, targetProp, Binding);
return Binding.ProvideValue(serviceProvider);
}
}