如何在WPF Visual Studio Designer中显示占位符值,直到可以加载实际值

时间:2009-03-29 20:02:11

标签: c# wpf visual-studio designer

我是一名经验丰富的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

5 个答案:

答案 0 :(得分:19)

在设计用户控件时,我经常在绑定上使用FallbackValue来查看内容。例如:

<TextBlock Text={Binding Path=AverageValue, FallbackValue=99.99} />

但是,由于FallbackValue不仅仅是在设计时应用,如果您想在运行时出于其他原因使用FallbackValue,这可能不合适。

答案 1 :(得分:2)

在您的示例中,您可能需要使用TargetNullValue,而不是FallbackValue,因为绑定表达式可能是null,因为DataContextnull 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)

TargetNullValueFallbackValue 在运行时都有函数,所以它们不是很好的占位符选择。
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);
    }
}