读取XML后,“更改颜色”不会影响属性更改

时间:2017-04-13 12:36:05

标签: c# wpf mvvm data-binding inotifypropertychanged

我使用observable collection来修改一个继承自INotifyPropertyChange

的Class

然而,当我更改文本框颜色时,它不会更改属性,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>

3 个答案:

答案 0 :(得分:2)

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

public string Color
{
    get
    {
        return color;
    }
    set
    {

        color = value;
        OnProperyChanged("Color");

    }
}

答案 1 :(得分:1)

您应该将属性的名称传递给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: 有点不清楚你期望发生什么,但如果你想设置Name中显示的实际项目的ColorListBox属性,你应该迭代这些:< / p>

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都返回新对象,则迭代这些对象是没有意义的。

答案 2 :(得分:0)

问题出在我已经重新编写XML的类中,这里没有继承SerialPortsColorReadWriteXML:INotifyPropertyChanged

function doGet() {
   var t = HtmlService.createTemplateFromFile('index.html');  
   var ss = SpreadsheetApp.openById('sheet_ID');
   var lrN = ss.getSheetByName('NCMR').getLastRow();

t.statArray = ss.getSheetByName('NCMR').getRange('Z3:Z'+lrN+'').getValues();

return t.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}