更改颜色不会影响读取 XML 后的属性更改



我使用可观察集合来 udpate 一个从INotifyPropertyChange继承的类

但是,当我更改文本框颜色时,它不会更改属性,并且PropertyChanged保持 null 并且不会触发。在第一次更改时,它不为空。但是在第一次更改之后,它始终为空。

附加我的代码:

namespace COMSimulator
{
    [XmlRoot("SerialPortsColors")]
    public  class SerialPortsColors: ObservableCollection< COM>
    {
    }
    public class COM : INotifyPropertyChanged
    {
        private string name;
        private string color;
        [XmlAttribute("Name")]
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
                OnProperyChanged(name);
            }
        }
        [XmlAttribute("Color")]
        public string Color
        {
            get
            {
                return color;
            }
            set
            {
                OnProperyChanged(value);
                color = value;
            }
        }
        public COM()
        {
            name = "";
            color = "";
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnProperyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

窗口代码隐藏:

public partial class colorPickerWindow : Window
{
    private SerialPortsColorReadWriteXML _SerialPortsColorReadWriteXML;        
    public colorPickerWindow()
    {
        InitializeComponent();            
        updateSerialPorts();
        _SerialPortsColorReadWriteXML = new SerialPortsColorReadWriteXML();            
        string err = _SerialPortsColorReadWriteXML.ReadXML();
        if (err != "")
        {
            MessageBox.Show(err);
            return;
        }
        LBSerialAndColors.ItemsSource = _SerialPortsColorReadWriteXML.LSerialPortsColors;
    }
    private void updateSerialPorts()
    { 
        string [] PortName = System.IO.Ports.SerialPort.GetPortNames();
        for (int i = 0; i <PortName.Length; i++)
        {
            CB_SelecComPort.Items.Add(PortName[i]);
        }
    }
    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        string err=""; //case there is an error
        string COM_TEXT = CB_SelecComPort.Text;
        MySerialPort.FuncConverstion.checkComName(ref COM_TEXT,ref err);
        if (_colorPicker.SelectedColor == null)
        {
            MessageBox.Show("Please Select a color");
            return;
        }
        if (err!="")
        {
            MessageBox.Show(err);
            return;
        }
        for (int i = 0; i < _SerialPortsColorReadWriteXML.LSerialPortsColors.Count; i++)
        {
            if (_SerialPortsColorReadWriteXML.LSerialPortsColors[i].Name == CB_SelecComPort.Text)
            {
                _SerialPortsColorReadWriteXML.LSerialPortsColors[i].Color = _colorPicker.SelectedColor.Value.R.ToString("X2") + _colorPicker.SelectedColor.Value.G.ToString("X2") + _colorPicker.SelectedColor.Value.B.ToString("X2") + _colorPicker.SelectedColor.Value.A.ToString("X2"); //R G B A                    
                _SerialPortsColorReadWriteXML.WriteXML();
                _SerialPortsColorReadWriteXML.ReadXML();
                MessageBox.Show("Serial Port and Color has been updated");
                return;
            }
        }
        COM NewCom = new COM ();  
        NewCom.Color = _colorPicker.SelectedColor.Value.R.ToString("X2") + _colorPicker.SelectedColor.Value.G.ToString("X2") + _colorPicker.SelectedColor.Value.B.ToString("X2") + _colorPicker.SelectedColor.Value.A.ToString("X2"); //R G B A                    
        NewCom.Name = CB_SelecComPort.Text;
        _SerialPortsColorReadWriteXML.LSerialPortsColors.Add(NewCom);
        _SerialPortsColorReadWriteXML.WriteXML();
        _SerialPortsColorReadWriteXML.ReadXML();
        MessageBox.Show("Serial Port and Color has been updated");
    }
}

public class COMColorConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string Color_bytes = value.ToString();
        string R = Color_bytes[0].ToString() + Color_bytes[1].ToString();
        string G = Color_bytes[2].ToString() + Color_bytes[3].ToString();
        string B = Color_bytes[4].ToString() + Color_bytes[5].ToString();
        string A = Color_bytes[6].ToString() + Color_bytes[7].ToString();
        Color _Color = new Color();
        _Color.R = byte.Parse(R,System.Globalization.NumberStyles.AllowHexSpecifier);
        _Color.G = byte.Parse(G, System.Globalization.NumberStyles.AllowHexSpecifier);
        _Color.B = byte.Parse(B, System.Globalization.NumberStyles.AllowHexSpecifier);
        _Color.A = byte.Parse(A, System.Globalization.NumberStyles.AllowHexSpecifier);
        SolidColorBrush SCB = new SolidColorBrush(_Color);
        return SCB;

    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public class SerialPortsColorReadWriteXML:
{
    private SerialPortsColors _LSerialPortsColors;

    public SerialPortsColorReadWriteXML()
    {
        _LSerialPortsColors = new SerialPortsColors();
    }
    public SerialPortsColors LSerialPortsColors
    {
        get
        {
            return _LSerialPortsColors;
        }
        set
        {
            _LSerialPortsColors = value;
        }
    }
    private  string path = "SerialPortsColors.xml";        

    /// <summary>
    /// read the serial ports color XML
    /// </summary>
    /// <returns>In Case of an error return the error</returns>
    public  string ReadXML()
    {            
        XmlSerializer serializer = new XmlSerializer(typeof(SerialPortsColors));
        try
        {
            using (XmlReader reader = XmlReader.Create(path))
            {
                LSerialPortsColors = (SerialPortsColors)serializer.Deserialize(reader);                    
            }
            return "";
        }
        catch  (Exception )
        {
            return "There is an issue with the path of the Serial Ports Color XML";
        }

    }

    public  string WriteXML()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(SerialPortsColors));
        try
        {
            XmlWriterSettings xws = new XmlWriterSettings();
            xws.Indent = true;
            using (XmlWriter writer = XmlWriter.Create(path, xws))
            {

                serializer.Serialize(writer, LSerialPortsColors);
            }
            return "";
        }
        catch
        {
            return  "There is an issue Creating a new XML File";
        }            
    }


}

XAML:

<Window x:Class="COMSimulator.colorPickerWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
    xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"  
    xmlns:Converters="clr-namespace:COMSimulator"
    Title="colorPickerWindow" Height="400" Width="300" WindowState="Normal" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
<Window.Resources>
    <Converters:COMColorConverter x:Key="COMColorConverter" />
</Window.Resources>
<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="COMColorTemplate">
            <Border BorderBrush="Black" BorderThickness="1">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*"></ColumnDefinition>
                        <ColumnDefinition Width="1*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBox Grid.Column="0" Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }" HorizontalAlignment="Left"  VerticalAlignment="Center" Width="100" />
                    <TextBlock Grid.Column="1" HorizontalAlignment="Left" Width="150"  Background="{Binding UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Path=Color, Converter={StaticResource COMColorConverter}}" ></TextBlock>                                            
            </Grid>
            </Border>
        </DataTemplate>
    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition Height="120"/>
        <RowDefinition Height="3"/>
        <RowDefinition Height="1*"/>
    </Grid.RowDefinitions>
    <Border Grid.Row="0" Grid.Column="0" BorderThickness="1" BorderBrush="Black">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"></RowDefinition>
            <RowDefinition Height="10"></RowDefinition>
            <RowDefinition Height="1*"></RowDefinition>
            <RowDefinition Height="10"></RowDefinition>
            <RowDefinition Height="1*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="5"></ColumnDefinition>
            </Grid.ColumnDefinitions>
        <Label Content="Select COM Port:" VerticalAlignment="Center" HorizontalAlignment="Center"></Label>
        <ComboBox x:Name="CB_SelecComPort" Grid.Column="1" Grid.Row="0" VerticalAlignment="Center"></ComboBox>
        <Label Content="Select Color:" VerticalAlignment="Center" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Center"></Label>
        <xctk:ColorPicker x:Name="_colorPicker" Grid.Column="1" Grid.Row="2" VerticalAlignment="Center" />
        <Button x:Name="btnAdd" Content="Add Or Edit" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="150" Click="btnAdd_Click"></Button>
    </Grid>
    </Border>
    <Border Grid.Row="2" Grid.Column="0" BorderThickness="1" BorderBrush="Black" >
        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
            <ListBox x:Name="LBSerialAndColors" ItemTemplate="{DynamicResource COMColorTemplate}" >
            </ListBox>
        </ScrollViewer>
    </Border>
</Grid>
</Window>

在更改颜色之前,您正在通知 UI 您的颜色已更改。试试这个:

public string Color
{
    get
    {
        return color;
    }
    set
    {
        color = value;
        OnProperyChanged("Color");
    }
}
您应该将

属性的名称传递给 OnPropertyChanged 方法,即 OnProperyChanged("Name")而不是OnProperyChanged(name)

public string Name
{
    get
    {
        return name;
    }
    set
    {
        name = value;
        OnProperyChanged("Name");
    }
}
[XmlAttribute("Color")]
public string Color
{
    get
    {
        return color;
    }
    set
    {
        color = value;
        OnProperyChanged("Color");
    }
}

此外,请确保在引发PropertyChanged事件之前设置支持字段。

编辑:正如@john所评论的那样,您可以在 C#6 或更高版本中使用 nameof 运算符:

OnProperyChanged(nameof(Color));

编辑 2:目前还不清楚您期望发生什么,但如果要设置ListBox中显示的实际项的 NameColor 属性,则应遍历这些属性:

foreach(var item in LBSerialAndColors.Items.OfType<COM>())
{
    if (item.Name == CB_SelecComPort.Text)
    {
        item.Color = _colorPicker.SelectedColor.Value.R.ToString("X2") + _colorPicker.SelectedColor.Value.G.ToString("X2") + _colorPicker.SelectedColor.Value.B.ToString("X2") + _colorPicker.SelectedColor.Value.A.ToString("X2"); //R G B A                    
        MessageBox.Show("Serial Port and Color has been updated");
        return;
    }
}

如果每次调用属性时_SerialPortsColorReadWriteXML.LSerialPortsColors都返回新对象,则循环访问这些对象是没有意义的。

问题出在我读取XML的类中,这里没有SerialPortsColorReadWriteXML:INotifyPropertyChanged

public class SerialPortsColorReadWriteXML:INotifyPropertyChanged
{
    private SerialPortsColors _LSerialPortsColors;

    public SerialPortsColorReadWriteXML()
    {
        _LSerialPortsColors = new SerialPortsColors();
    }
    public SerialPortsColors LSerialPortsColors
    {
        get
        {
            return _LSerialPortsColors;
        }
        set
        {
            _LSerialPortsColors = value;
            OnProperyChanged("LSerialPortsColors");
        }
    }
    private  string path = "SerialPortsColors.xml";        

    /// <summary>
    /// read the serial ports color XML
    /// </summary>
    /// <returns>In Case of an error return the error</returns>
    public  string ReadXML()
    {            
        XmlSerializer serializer = new XmlSerializer(typeof(SerialPortsColors));
        try
        {
            using (XmlReader reader = XmlReader.Create(path))
            {
                LSerialPortsColors = (SerialPortsColors)serializer.Deserialize(reader);                    
            }
            return "";
        }
        catch  (Exception )
        {
            return "There is an issue with the path of the Serial Ports Color XML";
        }

    }

    public  string WriteXML()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(SerialPortsColors));
        try
        {
            XmlWriterSettings xws = new XmlWriterSettings();
            xws.Indent = true;
            using (XmlWriter writer = XmlWriter.Create(path, xws))
            {

                serializer.Serialize(writer, LSerialPortsColors);
            }
            return "";
        }
        catch
        {
            return  "There is an issue Creating a new XML File";
        }            
    }


    public event PropertyChangedEventHandler PropertyChanged;
    private void OnProperyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

最新更新