WPF 通过后台绑定数据
简介
WPF 中的 Data binding 为应用程序呈现数据和与数据交互提供了一种简单且一致的方式。元素可以以 .NET 对象和 XML 的形式绑定到来自不同类型数据源的数据。
但是有些特殊情况下只能通过后台 FrameworkElement.SetBinding 绑定数据。
示例
示例为项目需要迁移到 .Net Framework 4.5.2 的 FFME 库。
SetBinding 介绍
第一个参数为用户控件的 依赖属性。
第二个参数为 Binding 类,同时可以设置要使用的转换器。
1 | namespace System.Windows |
公共 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
28internal class TimeSpanToSecondsConverter : IValueConverter
{
/// <inheritdoc />
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 : 0d;
default:
return 0d;
}
}
/// <inheritdoc />
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is double == false) return 0d;
var result = TimeSpan.FromTicks(System.Convert.ToInt64(TimeSpan.TicksPerSecond * (double)value));
// Do the conversion from visibility to bool
if (targetType == typeof(TimeSpan)) return result;
return targetType == typeof(Duration) ?
new Duration(result) : Activator.CreateInstance(targetType);
}
}
前台绑定 Binding
App.xaml1
2
3<ResourceDictionary>
<local:TimeSpanToSecondsConverter x:Key="TimeSpanToSecondsConverter" />
</ResourceDictionary>
UserControl.xaml1
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.cs1
2
3
4
5
6
7
8
9
10
11
12
13
14private MediaElement m_MediaElement;
/// <summary>
/// Gets the media element hosted by the main window.
/// </summary>
public MediaElement MediaElement
{
get
{
if (m_MediaElement == null)
m_MediaElement = (Application.Current.MainWindow as MainWindow)?.Media;
return m_MediaElement;
}
}
后台绑定 SetBinding
UserControl.xaml1
<Slider Name="PositionSlider" Grid.Row="0" Margin="10,0" Cursor="Hand" IsSnapToTickEnabled="False"/>
UserControl.xaml.cs1
2
3
4
5
6
7
8PositionSlider.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 });