2

注意:这不仅仅是关于自定义标记扩展。请在标记为重复之前阅读。

我有一个带有转换器的 WPF 标记扩展,它们两个如下所示:

  [ValueConversion(typeof(WindowState), typeof(object))]
  internal class WindowStateToObjectConverter : IValueConverter {
    public WindowStateToObjectConverter() { }

    public WindowStateToObjectConverter(object maximized, object normal) {
      this.maximized = maximized;
      this.normal = normal;
    }

    #region Properties
    #region Maximized Property
    private object maximized;

    public object Maximized {
      get { return maximized; }
      set { maximized = value; }
    }
    #endregion
    #region Normal Property
    private object normal;

    public object Normal {
      get { return normal; }
      set { normal = value; }
    }
    #endregion
    #endregion

    public object Convert(object value, Type targetType, object param, CultureInfo culture) {
      if((value as WindowState? ?? WindowState.Normal) == WindowState.Maximized) return maximized;
      else return normal;
    }

    public object ConvertBack(object value, Type targetType, object param, CultureInfo culture) {
      throw new InvalidOperationException("Cannot convert downwards to WindowState");
    }
  }

  [MarkupExtensionReturnType(typeof(Binding))]
  internal class WindowMaximizedSwitchExtension : MarkupExtension {
    object maximized, normal;

    public WindowMaximizedSwitchExtension(object maximized, object normal) {
      this.maximized = maximized;
      this.normal = normal;
    }

    public override object ProvideValue(IServiceProvider serviceProvider) {
      Binding ret = new Binding("WindowState");
      RelativeSource retRSource = new RelativeSource(RelativeSourceMode.FindAncestor);
      retRSource.AncestorType = typeof(Window);
      ret.RelativeSource = retRSource;
      ret.Converter = new WindowStateToObjectConverter(maximized, normal);
      return ret.ProvideValue(serviceProvider);
    }
  }

它们用于我正在设计的自定义窗口 - 当窗口最大化时,它们将用于切换某些值(边框宽度、边距等)。然而,在设计时,它们总是返回 null,这真的很痛苦,因为我的窗口看起来像这样:

在 Visual Studio 中预览窗口

...当它应该看起来像这样时:

运行时的窗口

(忽略第一张图片中缺少标题和图标,但是,如果您有解决方案,请随时回答 - 这本质上是同一个问题。)

出于显而易见的原因,使用它进行设计将非常困难。您在窗口预览中看到的唯一主要问题是我使用扩展名设置Row/ ColumnDefinitions 的地方 - 当它返回 null 时,Height/Width设置为1*. 所以,我的问题是是否有办法在设计时选择默认值,而不是绑定(例如非最大化值)。

4

1 回答 1

5

好吧,我觉得自己像个白痴,但我很快找到了解决方案:

ProvideValue表达式的方法中,我添加了以下行:

  ret.FallbackValue = normal;

normal窗口未最大化时使用的值在哪里。

ProvideValue现在看起来像这样:

public override object ProvideValue(IServiceProvider serviceProvider) {
  Binding ret = new Binding("WindowState");
  RelativeSource retRSource = new RelativeSource(RelativeSourceMode.FindAncestor);
  retRSource.AncestorType = typeof(Window);
  ret.RelativeSource = retRSource;
  ret.Converter = new WindowStateToObjectConverter(maximized, normal);
  ret.FallbackValue = normal;
  return ret.ProvideValue(serviceProvider);
}

这将在设计时返回正常值。

于 2014-03-09T23:37:26.367 回答