none
WPF 主窗体使用用户控件(此用户控件又嵌套使用了另外一个用户控件)的数据绑定问题 RRS feed

  • 问题

  • 你好,我现在在做一个WPF软件. 在主窗体中怎么将数据绑定到嵌套的用户控件中呢?
      软件的控件引用顺序:
    “MainWindow” --》包含2个用户控件A“local:Bw900Info”--》用户控件A又嵌套了用户控件B“local:BatteryUserControl”   
    程序的目的是想将电池电量SlaveBattery绑定到嵌套的用户控件B“local:BatteryUserControl”中显示出来。
      数据绑定过程是:
        将用户数据“SlaveBattery” 绑定到用户控件A的“SlaveBattery”属性,然后用户控件A的“SlaveBattery”属性再绑定到用户控件B的“Battery”属性,最终由
     用户控件B显示。 
         用户数据绑定到用户控件A属性:SlaveBattery="{Binding Path=SlaveBattery}" 
         用用户控件A自定义属性绑定到用户控件B属性: Battery="{Binding Path=SlaveBattery,Mode=TwoWay}"
     
    现在的问题是:数据绑定只能绑定到用户控件A,主窗体数据虽然间接绑定了用户控件B的属性,但是当用户数据修改时,用户控件B并没有修改。

    下面是部分代码说明:
    ================================================

    新建用户数据RFParamClass类,并且实现INotifyPropertyChanged接口;

        public   class RFParamClass : INotifyPropertyChanged
        {
            /// <summary>
            /// 属性变化引发的事件 INotifyPropertyChanged
            /// </summary>
            public event PropertyChangedEventHandler PropertyChanged;
            public void OnPropertyChanged(PropertyChangedEventArgs e)
            {
                if (PropertyChanged != null)
                {
                    //引发事件
                    PropertyChanged(this, e);
                }
            }
    // 显示电池电量,这个数据是要绑定到嵌套的用户控件中

          int slaveBattery = 5;
            public int SlaveBattery
            {
                get
                {
                    return slaveBattery;
                }
                set
                {
                    slaveBattery = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("SlaveBattery"));
                }
            }
    }

    然后在APP.xaml.cs里面定义了全局变量
       ObservableCollection<RFParamClass> slaveParam,
       且在主窗体构造函数里 指定用户控件的DataContent:
       SlaveIndex0.DataContent=(Application.Current as App).slaveParam[0],
       SlaveIndex1.DataContent=(Application.Current as App).slaveParam[1],

    ==================================================================

    下面是主窗体XAML的部分代码:

     注:local:Bw900Info 是用户控件A, 用户控件A中的自定义依赖项属性SlaveBattery绑定到用户数据slaveParam[0].SlaveBattery
    <wndow x:Class ...>
          <Grid>
                        <local:Bw900Info Grid.Column="1" Width="76"  x:Name="SlaveInex1"
                                         SlaveBattery="{Binding Path=SlaveBattery}"      
                                         ></local:Bw900Info>
                        <local:Bw900Info Grid.Column="1" Width="76"  x:Name="SlaveInex2"
                                         SlaveBattery="{Binding Path=SlaveBattery}"
                                         ></local:Bw900Info>
       </Grid>
    </Window>
    ==============================
     用户控件A “local:Bw900Info”的  依赖项属性:
            public static readonly DependencyProperty SlaveBatteryPropety = DependencyProperty.Register(
          "SlaveBattery", typeof(int), typeof(Bw900Info), new PropertyMetadata(null));
            public int SlaveBattery
            {
                get
                {
                    return (int)GetValue(SlaveBatteryPropety);
                }
                set
                {
                    SetValue(SlaveBatteryPropety, value);
                }
            }
     用户控件A “local:Bw900Info”的 XAML:(其中:local:BatteryUserControl 是嵌套的用户控件B )
    < UserControl ....
                <local:BatteryUserControl Grid.Row="8" x:Name="user_Battery"
                                          Battery="{Binding Path=SlaveBattery,Mode=TwoWay}"
                                           MouseDown="user_Battery_MouseDown" 
                                          ></local:BatteryUserControl>
    </UserControl>
     =======================================
    用户控件B "local:BatteryUserControl"的XAML代码:
    <UserControl x:Class="BW900ControlPanel.BatteryUserControl"
                ...
                 d:DesignHeight="130" d:DesignWidth="75"
                 Name="BatteryInfo"
                    
                 >

        <UserControl.Resources>
            <SolidColorBrush x:Key="DefualtBrush" Color="#FF3B3B3B"></SolidColorBrush>
            <Color x:Key="DefualtColor">#FF3B3B3B</Color>
        </UserControl.Resources>
        
        <Canvas Background="#FF1C1E28" SnapsToDevicePixels="False">
            <Line Canvas.Left="0" Canvas.Top="13" Stroke="#FF131217" X1="0" Y1="0" X2="75" Y2="0"></Line>
            <Line Canvas.Left="0" Canvas.Top="32" Stroke="#FF131217" X1="0" Y1="0" X2="75" Y2="0"></Line>
            <Line Canvas.Left="0" Canvas.Top="52" Stroke="#FF131217" X1="0" Y1="0" X2="75" Y2="0"></Line>
            <Line Canvas.Left="0" Canvas.Top="72" Stroke="#FF131217" X1="0" Y1="0" X2="75" Y2="0"></Line>
            <Line Canvas.Left="0" Canvas.Top="94" Stroke="#FF131217" X1="0" Y1="0" X2="75" Y2="0"></Line>
            <Rectangle Name="Batt_Low" Canvas.Left="18" Canvas.Top="112" Width="31" Height="8" Fill="{StaticResource DefualtBrush}"></Rectangle>
            <!--电池外壳 坐标从左肩开始 #FFD38A46  -->
            <Polygon Name="BattInfo" Canvas.Left="12" Canvas.Top="2"  Stroke="{StaticResource DefualtBrush}" StrokeThickness="2"
                     Points="0,12 0,89 
                             1,90 
                             2,91 41,91
                             42,90
                             43,89 43,12 
                             42,11 
                             41,10 30,10 
                             30,3
                             28,2 16,2
                             14,3
                             14,3 14,10
                             2,10
                     "
                     ></Polygon>
            <Polygon Name="Batt_5" Canvas.Left="18" Canvas.Top="19"  Fill="{StaticResource DefualtBrush}" StrokeThickness="0"
                Points=" 0,0 0,8 32,17 32,0  "
                >
            </Polygon>
            <Polygon Name="Batt_4" Canvas.Left="18" Canvas.Top="28"  Fill="{StaticResource DefualtBrush}" StrokeThickness="0"
                Points=" 0,0 0,13 32,22 32,9  " RenderTransformOrigin="0.493,0.244"
                ></Polygon>
            <Polygon Name="Batt_3" Canvas.Left="18" Canvas.Top="42"  Fill="{StaticResource DefualtBrush}" StrokeThickness="0"
                Points=" 0,0 0,13 32,22 32,9  "
                ></Polygon>
            <Polygon Name="Batt_2" Canvas.Left="18" Canvas.Top="56"  Fill="{StaticResource DefualtBrush}" StrokeThickness="0"
                Points=" 0,0 0,13 32,22 32,9  "
                ></Polygon>
            <Polygon Name="Batt_1" Canvas.Left="18" Canvas.Top="70"  Fill="{StaticResource DefualtBrush}" StrokeThickness="0"
                Points=" 0,0 0,17 32,17 32,9  "
                ></Polygon>  
            
        </Canvas>
    </UserControl>

    用户控件B "local:BatteryUserControl"的依赖性属性 :Battery


              public static readonly DependencyProperty BatteryPropety = DependencyProperty.Register( "Battery", typeof(int), typeof(BatteryUserControl),
                  new PropertyMetadata((int)0, new PropertyChangedCallback(OnPropertyChange)));
            public static readonly DependencyProperty IsBattShowEnablePropety = DependencyProperty.Register("IsBattShowEnable", typeof(bool), typeof(BatteryUserControl), 
               new PropertyMetadata((bool)false, new PropertyChangedCallback(OnPropertyChange)));


            public int Battery
            {
                get
                {
                    return (int)GetValue(BatteryPropety);
                }
                set
                {
                    SetValue(BatteryPropety, value);
                }
            }
            public bool IsBattShowEnable
            {
                get
                {
                    return (bool)GetValue(IsBattShowEnablePropety);
                }
                set
                {
                    SetValue(IsBattShowEnablePropety, value);
                }
            }

               //依赖性属性改变,显示不同的电池余量百分比,用多边形显示
            static void OnPropertyChange(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                BatteryUserControl buc = sender as BatteryUserControl;
                if (buc.IsBattShowEnable)
                {

                    switch (buc.Battery)
                    {
                        case 5:
                            buc.Batt_5.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_4.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_3.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_2.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_1.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.BattInfo.Stroke = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_Low.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            break;
                        case 4:
                            buc.Batt_5.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_4.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_3.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_2.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_1.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.BattInfo.Stroke = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_Low.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            break;
                        case 3:
                            buc.Batt_5.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_4.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_3.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_2.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_1.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.BattInfo.Stroke = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_Low.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            break;
                        case 2:
                            buc.Batt_5.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_4.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_3.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_2.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_1.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.BattInfo.Stroke = new SolidColorBrush(Color.FromArgb(255, 255, 130, 63));
                            buc.Batt_Low.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            break;
                        case 1:
                            buc.Batt_5.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_4.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_3.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_2.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_1.Fill = new SolidColorBrush(Color.FromArgb(255, 244, 28, 67));
                            buc.BattInfo.Stroke = new SolidColorBrush(Color.FromArgb(255, 244, 28, 67));
                            buc.Batt_Low.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            break;
                        default:
                        case 0:
                            buc.Batt_5.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_4.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_3.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_2.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.Batt_1.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                            buc.BattInfo.Stroke = new SolidColorBrush(Color.FromArgb(255, 244, 28, 67));
                            buc.Batt_Low.Fill = new SolidColorBrush(Color.FromArgb(255, 244, 28, 67));
                            break;
                    }

                }
                else
                {
                    buc.Batt_5.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                    buc.Batt_4.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                    buc.Batt_3.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                    buc.Batt_2.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                    buc.Batt_1.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                    buc.BattInfo.Stroke = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                    buc.Batt_Low.Fill = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                }
            }

    下面是图片:
     


    2017年8月18日 11:24

答案

  • Hi,

    >> 将用户数据“SlaveBattery” 绑定到用户控件A的“SlaveBattery”属性,然后用户控件A的“SlaveBattery”属性再绑定到用户控件B的“Battery”属性,最终由用户控件B显示。

    因为子元素的DataContex默认继承父元素的DataContext.所以你需要指定UserControl的DataContext.

    控件B:

    <UserControl .......
                  x.Name = "uc">
    <TextBlock Text="{Binding Battery,Mode=TwoWay,ElementName=uc}"/>

    控件A:

    <UserControl .....
                 x:Name="uc">
    
    <local:B Battery="{Binding SlaveBattery,Mode=TwoWay,ElementName=uc}" />

    Window:

    <local: A SlaveBattery="{Binding SlaveBattery}"

    你也可以设置User Control的DataContext属性,如下:

    ElementName.DataContext = this; //这里的ElementName可以是你用来布局并承载的元素,

    如果我有任何误解,请附上一个可以复现问题的demo,这样有助于我们帮您分析问题。

    另外,请使用插入代码块的方式来显示你的代码,这样会使你的代码阅读起来更加容易。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • 已标记为答案 sunny.hgh 2017年8月22日 2:35
    2017年8月21日 11:25
    版主

全部回复

  • Hi,

    >> 将用户数据“SlaveBattery” 绑定到用户控件A的“SlaveBattery”属性,然后用户控件A的“SlaveBattery”属性再绑定到用户控件B的“Battery”属性,最终由用户控件B显示。

    因为子元素的DataContex默认继承父元素的DataContext.所以你需要指定UserControl的DataContext.

    控件B:

    <UserControl .......
                  x.Name = "uc">
    <TextBlock Text="{Binding Battery,Mode=TwoWay,ElementName=uc}"/>

    控件A:

    <UserControl .....
                 x:Name="uc">
    
    <local:B Battery="{Binding SlaveBattery,Mode=TwoWay,ElementName=uc}" />

    Window:

    <local: A SlaveBattery="{Binding SlaveBattery}"

    你也可以设置User Control的DataContext属性,如下:

    ElementName.DataContext = this; //这里的ElementName可以是你用来布局并承载的元素,

    如果我有任何误解,请附上一个可以复现问题的demo,这样有助于我们帮您分析问题。

    另外,请使用插入代码块的方式来显示你的代码,这样会使你的代码阅读起来更加容易。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • 已标记为答案 sunny.hgh 2017年8月22日 2:35
    2017年8月21日 11:25
    版主
  • 了解了,谢谢!
    2017年8月22日 2:35