内容简介:响应式布局在各种现代的 UI 框架中不是什么新鲜的概念,基本都是内置支持。然而在古老的 WPF 框架中却并没有原生支持,后来虽然通过 Blend 自带的 Interactions 库实现了响应式布局,但生成的代码量太大了,而且需要引入额外的库。如果只是希望临时局部地方使用响应式布局,那么其实可以直接使用 WPF 内置的绑定机制来完成响应式布局。本文介绍如何使用。
响应式布局在各种现代的 UI 框架中不是什么新鲜的概念,基本都是内置支持。然而在古老的 WPF 框架中却并没有原生支持,后来虽然通过 Blend 自带的 Interactions 库实现了响应式布局,但生成的代码量太大了,而且需要引入额外的库。
如果只是希望临时局部地方使用响应式布局,那么其实可以直接使用 WPF 内置的绑定机制来完成响应式布局。本文介绍如何使用。
思路是在控件尺寸发生变更的时候更新控件的样式。而能容易实现这个的只有 Trigger
和 Setter
那一套。直接在控件上使用的 Trigger
只能使用 EventTrigger
,因此我们需要编写能写更多种类 Trigger
的 Style
。
<Style x:Key="Style.Foo.WalterlvDemo"> <Setter Property="Grid.Row" Value="0" /> <Setter Property="Grid.Column" Value="0" /> <Style.Triggers> <DataTrigger Value="True" Binding="{Binding ActualHeight, ElementName=DemoWindow, Converter={StaticResource GreaterOrEqualsConverter}, ConverterParameter=640}"> <Setter Property="Grid.Row" Value="1" /> <Setter Property="Grid.Column" Value="1" /> </DataTrigger> </Style.Triggers> </Style>
定义了一个样式,默认情况下,行列是 (0, 0),当窗口宽度大于或等于 640 之后,行列换到 (1, 1)。
这里我们需要一个大于或等于,以及小于的转换器。
using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Data; namespace Cvte.EasiNote.UI.Styles.Converters { public class GreaterOrEqualsConverter : IValueConverter { public double Than { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is double d) { return d >= Than; } else if (value is float f) { return f >= Than; } else if (value is ulong ul) { return ul >= Than; } else if (value is long l) { return l >= Than; } else if (value is uint ui) { return ui >= Than; } else if (value is int i) { return i >= Than; } else if (value is ushort us) { return us >= Than; } else if (value is short s) { return s >= Than; } else { return false; } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotSupportedException(); } }
public class LessConverter : IValueConverter { public double Than { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is double d) { return d < Than; } else if (value is float f) { return f < Than; } else if (value is ulong ul) { return ul < Than; } else if (value is long l) { return l < Than; } else if (value is uint ui) { return ui < Than; } else if (value is int i) { return i < Than; } else if (value is ushort us) { return us < Than; } else if (value is short s) { return s < Than; } else { return false; } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotSupportedException(); } } }
如果你本身是写的基础控件的样式,那么绑定当然就跟本文一开始说的写法非常类似了。
如果你需要写的是一般控件,可以考虑直接在控件里写 <Framework.Style />
把样式内联进去。
如果你写的是 DataTemplate
,也一样是使用 DataTrigger
绑定。
你也可以不绑定到窗口上,而绑定到控件本身上,使用 TemplatedParent
作为绑定的源即可。
<DataTemplate> <DataTemplate.Resources> <local:LessConverter x:Key="LessThan60" Than="60" /> </DataTemplate.Resources> <Grid> <Image x:Name="Icon" /> <Rectangle x:Name="Mask" Fill="Red" /> </Grid> <DataTemplate.Triggers> <DataTrigger Binding="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource LessThan60}}" Value="True"> <Setter TargetName="Icon" Property="Grid.ColumnSpan" Value="3" /> <Setter TargetName="Mask" Property="Visibility" Value="Collapsed" /> </DataTrigger> </DataTemplate>
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。