设计时XAML的默认值

35

我有一个绑定的TextBlock,XAML:

<TextBlock Text="{Binding MyText}"/>
我知道如果绑定不可用,可以使用FallbackValue,但这是在运行时发生的吗?有没有办法在设计时显示默认值?如果我能在设计窗口时看到一个值而不是一个空的TextBlock,那会让事情变得更容易。
谢谢。

4
您可以设置一个虚拟的 ViewModel 作为数据上下文,其中应该已经将 MyText 属性初始化为某个值。 - Novitchi S
可能是[如何在XAML编辑器中查看设计时数据绑定(它在运行时有效)?]的重复问题(https://dev59.com/uGQn5IYBdhLWcg3w_LXx)。 - StayOnTarget
4个回答

64

更新: Visual Studio 2019 v16.7

现在你可以:

<TextBlock Text="{Binding MyText}" d:Text="Design time value"/>

如果你希望看到一个更简洁的版本,可以直接这样做:Ian Bamforth的回答.

<TextBlock Text="{Binding MyText, FallbackValue=None}"/>

5
有没有一种只在设计时生效的备用值?-- 如果视图模型中的属性为空,我不希望这些值出现。 - BrainSlugs83
我怀疑你需要一个适当的设计时视图模型来完全处理那种情况。但是,如果你特别担心现有属性具有空值,你可以使用 TargetNullValue 属性来指出它。 - Scroog1
6
这段文字听起来很不错,但目前仅限于“WPF .NET Core 和 UWP 项目”。 - jvcleave
7
他们已经推出了一个修复方案。此功能在预览渠道中也可用于.NET Framework。要启用它,请转到“工具”>“选项”>“环境”>“预览功能”,选择“.NET Framework的新WPF XAML设计器”,然后重新启动Visual Studio。 - DefenestrationDay

8

这个问题的例子中进行适应。

对我来说,这个方法有效 - 设计师中显示了文本“None”:

 <TextBlock>
    <TextBlock.Text>
        <Binding ElementName="root" Path="blah" FallbackValue="None" />
    </TextBlock.Text>
</TextBlock>

希望能对您有所帮助。

你能解释一下吗?也许我漏掉了什么,但这展示了如何在Margin属性上设置FallBackValue...? - Sherlock
9
我下投票反对这个,因为FallbackValue是在无法解析绑定时显示的值。如果你在XAML中指定了数据上下文(或数据上下文类型),这个解决方案就不会起作用,因为绑定可以成功解析(在我的情况下,元素被折叠起来,但我不想在设计时间看到它被折叠)。 - Geoffrey

6

使用FallbackValue是错误的,因为它也会影响运行时行为(如果绑定无法从源获取值,将使用回退值)。

我设计了一个自定义标记扩展,模仿Binding(最好能够继承Binding,但ProvideValue方法不是虚方法...):

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;

namespace MyNamespace
{
    public class BindingEx : MarkupExtension
    {
        private readonly Binding _binding;

        public BindingEx()
        {
            _binding = new Binding();
        }

        public BindingEx(string path)
        {
            _binding = new Binding(path);
        }

        public PropertyPath Path
        {
            get => _binding.Path;
            set => _binding.Path = value;
        }

        public BindingMode Mode
        {
            get => _binding.Mode;
            set => _binding.Mode = value;
        }

        public RelativeSource RelativeSource
        {
            get => _binding.RelativeSource;
            set => _binding.RelativeSource = value;
        }

        public string ElementName
        {
            get => _binding.ElementName;
            set => _binding.ElementName = value;
        }

        public IValueConverter Converter
        {
            get => _binding.Converter;
            set => _binding.Converter = value;
        }

        public object DesignValue { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            var target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
            if (target.TargetObject is DependencyObject d && DesignerProperties.GetIsInDesignMode(d))
                return DesignValue;

            return _binding.ProvideValue(serviceProvider);
        }
    }
}

您可以像使用Binding一样使用它,只需添加DesignValue属性即可:
<TextBlock Text="{my:BindingEx Name, DesignValue=John Doe}" />

请注意,BindingEx并没有Binding所有的属性,但如果需要,你可以很容易地添加它们。

这太棒了! - Efthymios

1
如果您已将此数据绑定并使用MVVM架构,则为其绑定的模型项设置默认值将在设计时显示该值。
我只是使用:

Model.cs:

private int frame = 999999;
public int Frame
{
  get { return frame; }
  set
  {
    frame = value;
    NotifyPropertyChanged(m => m.Frame);
  }
}

而在我的XAML中:

 <TextBlock Text="{Binding Path=Frame}"  />

设计师中显示的默认值为“999999”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接