【WPF】后台数据绑定
有很多时候,自定义控件是由多个不同的系统提供的控件组合起来的,那么在Xaml前端界面上,实例化对象之后,是没有办法访问到内部的控件的(哪怕你命了名),但是又想给他绑定数据源怎么办呢?
情景
<ProgressBar Grid.Row="0" x:Name="progressBar" x:FieldModifier="public" Style="{StaticResource ProgressBarStyle2}"
local:EllipseClipper.IsClipping="True" HorizontalAlignment="Center" Height="100" VerticalAlignment="Top"
Width="100" Value="50" RenderTransformOrigin="0.5,0.5" Foreground="{DynamicResource BodorBkColor}">
<ProgressBar.Effect>
<DropShadowEffect BlurRadius="7" Direction="-500" Color="#FF3E3E3E" RenderingBias="Quality" FrameworkElement.FlowDirection="LeftToRight" ShadowDepth="1" />
</ProgressBar.Effect>
<ProgressBar.Background>
<RadialGradientBrush>
<GradientStop Color="#363636" Offset="1" />
<GradientStop Color="#656666" />
</RadialGradientBrush>
</ProgressBar.Background>
<ProgressBar.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</ProgressBar.RenderTransform>
</ProgressBar>
<Label Grid.Row="1" x:Name="labelModelName" x:FieldModifier="public" Content="功率(KW)" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="{StaticResource NormalForeground}" FontSize="15"/>
<Label Grid.Row="0" x:Name="labelValue" x:FieldModifier="public" Content="{Binding Value, ElementName=progressBar,Converter={StaticResource ValueConverter}}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="{StaticResource NormalForeground}" FontSize="15" SizeChanged="labelValue_SizeChanged"/>
这段xaml的代码不保证有效,只是举个例子随便截取的一段,这个自定义控件由一个ProgreeBar和两个Label组成,其中Label1的Content绑定的是ProgressBar的Value,那么在外部调用这个自定义控件时
<local:LocalUserControl x:Name="localUserControl" Grid.Column="0" Width="120" />
这个时候已经访问不到内部的ProgressBar了,怎么绑定数据就是一个问题了
也不可能在控件里就绑定,那所有的控件绑定的都是一个数据源了
后台绑定
之前说xaml里哪怕内部的控件命了名也访问不了,那么命名干什么呢?是为了让后台代码可以访问到
//绑定当前速度
CurrentSpeedBall.progressBar.Maximum = 100;
SetBindings(CurrentSpeedBall.progressBar, viewModel.motionStatus, "Data", BindingMode.OneWay, ProgressBar.ValueProperty);
//绑定和初始化进给倍率
viewModel.motionStatus.feedRate = BusinessLayerService.CommonControlStatus.FeedRate = 100;
SetBindings(FeedRateSlider.slider, viewModel.motionStatus, "feedRate", BindingMode.TwoWay, Slider.ValueProperty);
后台是可以通过命名+.+命名的方式访问到内部的控件的
SetBinding & BindingOperations
这两者没什么大的区别,只是使用方法略微不同
如果需要封装成函数,控件的类型写UserControl会无法转换,所以应该写FrameWorkElement
-
SetBinding使用:
UserControl.SetBinding(DependcyProperty dp,BindingBase binding) -
BindingOperations使用:
BindingOperations.SetBinding(Obj, DepProperty, binding); -
Binding.Source
数据源,一般都是一个类 -
Binding.Path
双向绑定的时候或者数据源是类的时候会需要,如果数据源是类,path就是成员变量的名称 -
Binding.Mode
绑定的方式,和xaml里一致,one way/two way/…之类的,UpdateTrigger也是一样的设置方法
public void SetBindings(FrameworkElement Obj, Object Source, string PropertyPath, BindingMode Mode, DependencyProperty DepProperty)
{
Binding binding = new Binding();
binding.Source = Source;
binding.Path = new PropertyPath(PropertyPath);
binding.Mode = Mode;
if (Mode == BindingMode.TwoWay)
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(Obj, DepProperty, binding);
}
可能遇到的问题
如果绑定之后,界面UI没有变化,有可能是因为数据源没有通知UI发生了变化
数据源的类应该继承INotifyPropertyChanged,并且实现接口
public class DataSource : INotifyPropertyChanged
{
private double _Data;
public double Data
{
get { return _Data; }
set
{
_Data = value;
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Data"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
效果
上一篇: Android SDK 中常用的几个命令
推荐阅读