WPF 中使用转换器的问题

问题描述 投票:0回答:1

我的数据库中有一个与序列化字节数组相对应的字符串。我希望能够修改该字符串中存在的字节并添加或删除其中的一些字节。

我正在通过列表框绑定中存在的转换器将从数据库检索到视图模型的字符串转换为 XAML 中的字节列表。然后,我使用带有数据模板的文本框表示的字节数组。但问题是我无法将文本框中所做的更改检索回列表框,然后返回序列化字符串。 我尝试过的:

<ListBox ItemsSource="{Binding ByteArray, Converter={converter:HexStringToListOfBytesConverter}}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Path=., Mode=TwoWay}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我知道为什么它不起作用,但不知道如何让它起作用。我认为转换器不会影响文本框。理想情况下,字符串到字节数组的转换应该仅用于编辑现有的序列化数组。并且根据所做的修改制作的新的应该取代旧的。

c# wpf data-binding
1个回答
0
投票

您无法绑定到字符串

TwoWay
。您绑定到对象的properties,即绑定源。在 TwoWay 绑定中,您可以更改这些属性的值。这意味着,理论上,您可以绑定到字符串的属性来更改其内容。
此外,
string
是不可变的。

您必须引入包装类型来表示字节或字符表示。这样您就可以修改绑定源的属性值。

总的来说,你的方法过于复杂。您可以直接在

string
甚至
char
上工作。
char
byte
之间存在内置编译器转换。将
string
转换为
byte[]
只是将其转换回
string
以在视图中进行编辑是没有意义的。哪个人不喜欢编辑以字符而不是字节形式呈现的文本......
我建议将十六进制字符串转换为文本字符串并编辑这些值。

以下示例介绍了一个

ByteValue
包装器,并将转换封装在您可以直接绑定到的
ByteValueCollection
中。

ByteValue
使您能够编辑字节值和字符表示。 MainWindow.xaml.cs

public partial class MainWindow : Window
{
  public ByteValueCollection Bytes
  {
    get => (ByteValueCollection)GetValue(BytesProperty);
    set => SetValue(BytesProperty, value);
  }

  public static readonly DependencyProperty BytesProperty = DependencyProperty.Register(
    "Bytes",
    typeof(ByteValueCollection),
    typeof(MainWindow),
    new PropertyMetadata(default));

  public MainWindow()
  {
    InitializeComponent();

    string hexText = "48616C6C6F"; // Hallo
    this.Bytes = new ByteValueCollection(hexText);

    string hexText = "48 61 6C 6C 6F"; // Hallo
    this.Bytes = new ByteValueCollection(hexText, ' ');

    string hexString = this.Bytes.ToHexString(); // "48616C6C6F"
    string hexString = this.Bytes.ToHexString(' '); // "48 61 6C 6C 6F"
  }
}

MainWIndow.xaml

<Window x:Name="Root">
  <ListBox ItemsSource="{Binding ElementName=Root, Path=Bytes}">
    <ListBox.ItemTemplate>
      <DataTemplate DataType="{x:Type local:ByteValue}">
        <StackPanel Orientation="Horizontal">
          <TextBox Text="{Binding Character}" />
          <TextBox Text="{Binding Value}" />
        </StackPanel>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</Window>

ByteValue.cs

public class ByteValue : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler? PropertyChanged;
  public ByteValue(byte value) => this.Value = value;

  private byte value;
  public byte Value
  {
    get => this.value;
    set
    {
      this.value = (byte)value;
      OnPropertyChanged(null);
    }
  }

  public char Character
  {
    get => (char)this.Value;
    set
    {
      this.Value = (byte)value;
      OnPropertyChanged(null);
    }
  }

  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

ByteValueCollection.cs

public class ByteValueCollection : ObservableCollection<ByteValue>
{
  public ByteValueCollection()
  {
  }

  public ByteValueCollection(string hexString) : this(hexString, ' ')
  {
  }

  public ByteValueCollection(string hexString, char separator)
  {
    string[] hexTextValues = hexString.Split(separator);
    if (hexTextValues.Length != 1)
    {
      for (int index = 0; index < hexTextValues.Length; index++)
      {
        string hexTextValue = hexTextValues[index];
        byte byteValue = Convert.ToByte(hexTextValue, 16);
        var item = new ByteValue(byteValue);
        Add(item);
      }
    }
    else
    {
      for (int index = 0; index < hexString.Length; index += 2)
      {
        string hexTextValue = hexString.Substring(index, 2);
        byte byteValue = Convert.ToByte(hexTextValue, 16);
        var item = new ByteValue(byteValue);
        Add(item);
      }
    }
  }

  public ByteValueCollection(IEnumerable<ByteValue> collection) : base(collection)
  {
  }

  public ByteValueCollection(List<ByteValue> list) : base(list)
  {
  }

  public byte[] ToByteArray()
  {
    byte[] bytes = new byte[this.Count];
    for (int index = 0; index < bytes.Length; index++)
    {
      byte value = this[index].Value;
      bytes[index] = value;
    }

    return bytes;
  }

  public char[] ToCharArray()
  {
    char[] chars = new char[this.Count];
    for (int index = 0; index < chars.Length; index++)
    {
      char value = this[index].Character;
      chars[index] = value;
    }

    return chars;
  }

  public string ToHexString()
  {
    byte[] bytes = new byte[this.Count];
    for (int index = 0; index < bytes.Length; index++)
    {
      byte value = this[index].Value;
      bytes[index] = value;
    }

    return Convert.ToHexString(bytes);
  }

  public string ToHexString(char separator)
  {
    byte[] bytes = ToByteArray();
    string hexString = Convert.ToHexString(bytes);
    var hexStringBuilder = new StringBuilder(hexString);
    int separatorIndex = 2;
    for (int readInndex = 0; readInndex < this.Count - 1; readInndex++)
    {
        
      hexStringBuilder.Insert(separatorIndex, separator);
      separatorIndex += 3;
    }

    return hexStringBuilder.ToString();
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.