C# WPF-使用RelativeSource绑定为自定义标记扩展提供设计时值
N.B.:这不仅仅是关于自定义标记扩展。请在标记为副本之前阅读。 我有一个带有转换器的WPF标记扩展,其中两个如下所示:C# WPF-使用RelativeSource绑定为自定义标记扩展提供设计时值,c#,wpf,xaml,binding,markup-extensions,C#,Wpf,Xaml,Binding,Markup Extensions,N.B.:这不仅仅是关于自定义标记扩展。请在标记为副本之前阅读。 我有一个带有转换器的WPF标记扩展,其中两个如下所示: [ValueConversion(typeof(WindowState), typeof(object))] internal class WindowStateToObjectConverter : IValueConverter { public WindowStateToObjectConverter() { } public WindowSt
[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,这是一个真正的难题,因为我的窗口如下所示:
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);
}
…当它看起来像这样的时候:
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);
}
(忽略第一张图片中缺少标题和图标,不过,如果您有解决方案,请随意回答-这基本上是同一个问题。)
出于显而易见的原因,用这个进行设计是非常困难的。您在窗口预览中看到的唯一主要问题是我使用扩展设置
行
/列定义
s的位置-当它返回null时,高度
/宽度
设置为1*
。因此,我的问题是,是否有一种方法可以在设计时选择默认值,而不是绑定(例如,非最大化值)。嗯,我觉得自己像个白痴,但我很快找到了解决方案:
在表达式的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);
}
这将在设计期间返回正常值。我很惊讶我没有在网上找到这个答案……你可能会认为人们会发布/询问这个问题。再说一次,大多数人不是自学成才的。