欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【WPF】后台数据绑定

程序员文章站 2022-07-04 16:23:03
...

有很多时候,自定义控件是由多个不同的系统提供的控件组合起来的,那么在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;
    }

效果

【WPF】后台数据绑定

相关标签: C#