2

注意: これは、カスタム マークアップ拡張機能に関するものだけではありません。重複としてマークする前にお読みください。

コンバーターを使用した WPF マークアップ拡張機能があり、そのうちの 2 つは次のようになります。

  [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 でのウィンドウのプレビュー

...次のようになるはずの場合:

実行時のウィンドウ

(最初の画像でタイトルとアイコンが欠落していることは無視してください。ただし、解決策がある場合は、お気軽に回答してください。本質的には同じ問題です。)

明らかな理由から、これを使用して設計することは非常に困難です。ウィンドウのプレビューで見られる唯一の大きな問題は、拡張機能を使用して / を設定した場所です。null をRow返すColumnDefinitionと、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 に答える