1. 程式人生 > >WPF繫結失效問題(規避解決)

WPF繫結失效問題(規避解決)

使用WPF繫結後臺資料,在多次切換資料後繫結失效

將一個後臺資料繫結到多個RadioButton的IsChecked上,通過自定義轉換將整型資料轉換成bool型資料。點選介面上的新增按鈕,在button事件中,將繫結的物件資料加1,然後再前臺顯示,在多次後,前臺的RadioButton中會出現某個繫結失敗問題。

自定義轉換器程式碼:

#region 方法
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if
(value != null) { try { if (parameter != null) { int par = 0; if (int.TryParse(parameter.ToString(), out par)) { return
(value as int?).Value - par == 0; } return false; } else return false; } catch (System.Exception) { return false; } } return
false; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { try { if (parameter != null) { int par = 0; if (int.TryParse(parameter.ToString(), out par)) { if ((bool)value) return par; return null; } return 0; } else { return (bool)value ? 1 : 0; } } catch (System.Exception) { } return null; } #endregion

XAml程式碼:

<DockPanel x:Name="grid" LastChildFill="False">
        <DockPanel.DataContext>
            <local:Student/>
        </DockPanel.DataContext>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" HorizontalAlignment="Center" >
            <Button HorizontalAlignment="Center" Width ="60" Height="60" Click="Add_Click" Content="新增"/>
            <Button HorizontalAlignment="Center" Width ="60" Height="60" Click="Delete_Click" Content="刪除"/>
        </StackPanel>

        <RadioButton x:Name="rbtn_4" Content="test4" DockPanel.Dock="Top" IsChecked="{Binding Age, ConverterParameter=1, Converter={StaticResource IntToBoolConverter}}" GroupName="test2" Margin="0,10,0,0"/>
        <RadioButton x:Name="rbtn_5" Content="test5" DockPanel.Dock="Top" IsChecked="{Binding Age, ConverterParameter=2, Converter={StaticResource IntToBoolConverter}}" GroupName="test2"/>
        <RadioButton x:Name="rbtn_6" Content="test6" DockPanel.Dock="Top" IsChecked="{Binding Age, ConverterParameter=3, Converter={StaticResource IntToBoolConverter}}" GroupName="test2"/>
        <RadioButton x:Name="rbtn_7" Content="test7" DockPanel.Dock="Top" IsChecked="{Binding Age, ConverterParameter=4, Converter={StaticResource IntToBoolConverter}}" GroupName="test2"/>

        <TextBox DockPanel.Dock="Top" Margin="0,10,0,0" Text="{Binding Age, ConverterParameter=1, Converter={StaticResource IntToBoolConverter}}"></TextBox>
        <TextBox DockPanel.Dock="Top" Margin="0,10,0,0" Text="{Binding Age, ConverterParameter=2, Converter={StaticResource IntToBoolConverter}}"></TextBox>
        <TextBox DockPanel.Dock="Top" Margin="0,10,0,0" Text="{Binding Age, ConverterParameter=3, Converter={StaticResource IntToBoolConverter}}"></TextBox>
        <TextBox DockPanel.Dock="Top" Margin="0,10,0,0" Text="{Binding Age, ConverterParameter=4, Converter={StaticResource IntToBoolConverter}}"></TextBox>
    </DockPanel>

前臺程式碼:

private void Add_Click(object sender, RoutedEventArgs e)
 {
     Student tstd = grid.DataContext as Student;
     tstd.Age = tstd.Age % 4 + 1;
 }

Student:

class Student : INotifyPropertyChanged
    {
        #region 屬性
        string name;
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
                }
            }
        }
        public String ID
        {
            set;
            get;
        }
        int age = 1;
        public int Age
        {
            set
            {
                if (value == -1)
                    return;
                age = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Age"));
                }
            }
            get { return age; }
        }

        IP ip = new IP("127.0.0.1");
        public IP IP
        {
            get { return ip; }
            set
            {
                ip = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IP"));
                }
            }
        }
        #endregion

        #region 方法

        public Student Clone()
        {
            Student stu = new Student();
            stu.Name = this.Name;
            stu.Age = this.Age;
            stu.ID = this.ID + 1;
            return stu;
        }
        #endregion

        #region 事件
        #endregion
        public event PropertyChangedEventHandler PropertyChanged;
    }

目前的解決方案是使用CheckBox代替Radiobutton,同時針對CheckBox的Click方法額外處理(禁用Check的取消選中功能)。

private void CheckBox_Click(object sender, RoutedEventArgs e)
  {
      (sender as CheckBox).IsChecked = true;
      e.Handled = true;
  }

多個CheckBox之間的單選性採用繫結到同一個變數來處理(使用到上面的自定義轉換器)。

猜測:
單選按鈕同一組內按鈕的是否選中是關聯的,在你選中其中某個項時,底層會將其他選項的IsChecked屬性進行更新,此時與繫結衝突照成繫結的失效,而CheckBox是否選中只針對自己。