WPF 通过后台绑定数据
简介 WPF 中的 Data binding 为应用程序呈现数据和与数据交互提供了一种简单且一致的方式。元素可以以 .NET 对象和 XML 的形式绑定到来自不同类型数据源的数据。 但是有些特殊情况下只能通过后台 FrameworkElement.SetBinding 绑定数据。
示例 示例为项目需要迁移到 .Net Framework 4.5.2 的 FFME 库。
SetBinding 介绍 第一个参数为用户控件的 依赖属性 。 第二个参数为 Binding 类,同时可以设置要使用的转换器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 namespace System.Windows { [RuntimeNameProperty("Name" ) ] [StyleTypedProperty(Property = "FocusVisualStyle" , StyleTargetType = typeof(Control)) ] [UsableDuringInitialization(true) ] [XmlLangProperty("Language" ) ] public class FrameworkElement : UIElement , IFrameworkInputElement , IInputElement , ISupportInitialize , IHaveResources , IQueryAmbient { public BindingExpressionBase SetBinding (DependencyProperty dp, BindingBase binding ) ; } }
公共 IValueConverter 方法 用于提供将自定义逻辑应用于绑定的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 internal class TimeSpanToSecondsConverter : IValueConverter { public object Convert (object value , Type targetType, object parameter, CultureInfo culture ) { switch (value ) { case TimeSpan span: return span.TotalSeconds; case Duration duration: return duration.HasTimeSpan ? duration.TimeSpan.TotalSeconds : 0 d; default : return 0 d; } } public object ConvertBack (object value , Type targetType, object parameter, CultureInfo culture ) { if (value is double == false ) return 0 d; var result = TimeSpan.FromTicks(System.Convert.ToInt64(TimeSpan.TicksPerSecond * (double )value )); if (targetType == typeof (TimeSpan)) return result; return targetType == typeof (Duration) ? new Duration(result) : Activator.CreateInstance(targetType); } }
前台绑定 Binding App.xaml
1 2 3 <ResourceDictionary > <local:TimeSpanToSecondsConverter x:Key ="TimeSpanToSecondsConverter" /> </ResourceDictionary >
UserControl.xaml
1 2 3 4 5 6 7 8 <Slider Name ="PositionSlider" Grid.Row ="0" Margin ="10,0" Cursor ="Hand" IsSnapToTickEnabled ="False" IsEnabled ="{Binding MediaElement.IsOpen}" SmallChange ="{Binding MediaElement.PositionStep, Converter={StaticResource TimeSpanToSecondsConverter}}" LargeChange ="{Binding MediaElement.PositionStep, Converter={StaticResource TimeSpanToSecondsConverter}}" Minimum ="{Binding MediaElement.PlaybackStartTime, Converter={StaticResource TimeSpanToSecondsConverter}}" Maximum ="{Binding MediaElement.PlaybackEndTime, Converter={StaticResource TimeSpanToSecondsConverter}}" Value ="{Binding MediaElement.Position, Converter={StaticResource TimeSpanToSecondsConverter}}" />
UserControlViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private MediaElement m_MediaElement;public MediaElement MediaElement{ get { if (m_MediaElement == null ) m_MediaElement = (Application.Current.MainWindow as MainWindow)?.Media; return m_MediaElement; } }
后台绑定 SetBinding UserControl.xaml
1 <Slider Name ="PositionSlider" Grid.Row ="0" Margin ="10,0" Cursor ="Hand" IsSnapToTickEnabled ="False" />
UserControl.xaml.cs
1 2 3 4 5 6 7 8 PositionSlider.SetBinding(Slider.IsEnabledProperty, new Binding("IsOpen" ) { Source = this ._innerPlayer }); IValueConverter valueConverter = new TimeSpanToSecondsConverter(); PositionSlider.SetBinding(Slider.SmallChangeProperty, new Binding("PositionStep" ) { Source = this ._innerPlayer, Converter = valueConverter }); PositionSlider.SetBinding(Slider.LargeChangeProperty, new Binding("PositionStep" ) { Source = this ._innerPlayer, Converter = valueConverter }); PositionSlider.SetBinding(Slider.MinimumProperty, new Binding("PlaybackStartTime" ) { Source = this ._innerPlayer, Converter = valueConverter }); PositionSlider.SetBinding(Slider.MaximumProperty, new Binding("PlaybackEndTime" ) { Source = this ._innerPlayer, Converter = valueConverter }); PositionSlider.SetBinding(Slider.ValueProperty, new Binding("Position" ) { Source = this ._innerPlayer, Converter = valueConverter });