【发布时间】:2014-09-02 22:30:43
【问题描述】:
一个 WPF 窗口是否可以有多个布局?
也就是说,假设我有一个可以在平板电脑或更传统的台式机或笔记本电脑上运行的应用程序。该表格的屏幕分辨率可能比笔记本电脑或台式机高得多,但由于物理屏幕尺寸较小,最好在平板电脑上以不同的方式布置控件。
如果可以的话,你是怎么做到的?
【问题讨论】:
一个 WPF 窗口是否可以有多个布局?
也就是说,假设我有一个可以在平板电脑或更传统的台式机或笔记本电脑上运行的应用程序。该表格的屏幕分辨率可能比笔记本电脑或台式机高得多,但由于物理屏幕尺寸较小,最好在平板电脑上以不同的方式布置控件。
如果可以的话,你是怎么做到的?
【问题讨论】:
有许多不同的方法,根据您的需要,每种方法可能具有不同的优势。
具有不同默认值的附加属性,有条件地编译,带有查找该属性的项目样式/模板
将平台的输出考虑在内的值转换器
在代码中加载了多个 XAML
完全不同的平台页面,跨平台重用内部控件
实现相当于 Xamarin 的 OnIdiom,这可能是最好的方法。我用 OnIdiomExtension: IMarkupExtension 补充了我自己的实现,因此我可以在属性中使用它,而不必将它们分解为单独的元素
我相信这个列表可以继续下去,在 WPF 中总是有 10 种方法可以做同样的事情 - 9 种错误,1 种正确,1 种未记录通常是最好的 :)
编辑:OnIdiom 细节
本质上,OnIdiom 是一个通用构造,它选择 3 个元素之一 - OnTablet、OnPhone 和 OnDesktop - 每个都是其通用类型。您也可以选择仅使用 UIElement 作为其元素的非通用版本
这里有几个示例如何在 XAML 中使用它
<RowDefinition.Height>
<OnIdiom x:TypeArguments="GridLength" Phone="1.25*" Tablet="1.35*" />
</RowDefinition.Height>
<OnIdiom x:TypeArguments="View">
<OnIdiom.Phone>
<local:BuildingAreasView/>
</OnIdiom.Phone>
<OnIdiom.Tablet>
<Grid x:Name="gridRoot">....</Grid>
</OnIdiom.Tablet>
</OnIdiom>
以及 XAML 中使用的标记扩展:
这是来自 OnIdiomExtension.cs 的一些示例代码,为了简洁,显然缺少 Tablet 和 Desktop 属性
[ContentProperty ("Default")]
public class OnIdiomExtension : IMarkupExtension
{
public object Default { get; set; }
public object Phone { get; set; }
public object ProvideValue (IServiceProvider serviceProvider)
{
object val = Default;
switch (Device.Idiom) {
case TargetIdiom.Phone:
val = Phone ?? Default;
break;
}
return val;
}
}
【讨论】:
IMarkUpExtension 实现中,'Device` 对象来自哪里?