簡體   English   中英

WPF轉換器JSON字符串到多個文本框

[英]WPF Converter JSON string to multiple textboxes

由於工作時間的限制,我已經針對此問題做出了解決方法,盡管我仍然想出於學習目的。

因此,我遇到了一個問題,當時我正在為一些記錄數據創建編輯器屏幕,而該記錄中有一個名為“ Quantity”的字段。 但是,在設計時,它是一個數量占位符,但含義不同。 因此,要解釋一下,它是一個SkuReference表,其中包含一個“類型”,用於定義它是“每包數量”,“卷長”還是“ CBC”。 好吧,對於“每包數量”和“卷長”,一個簡單的數字有效,但是對於“ CBC”(即邊角/邊界/中心),數據存儲為JSON字符串對象:

{ 'Corners': 10, 'Borders': 20, 'Centers': 30 }

現在在WPF屏幕上,如果將數據標識為“ CBC”,則將數據路由到三個文本框,這些文本框均綁定到父對象的“ Quantity”屬性,並使用轉換器和參數來標識每個文本框,在每個文本框中輸入適當的值。 工作正常。

我遇到的問題是嘗試使用轉換器的ConvertBack部分時。 我意識到我沒有引用原始的字符串屬性,我可以編輯該屬性並為其提供新值,也不能訪問其他文本框來重建一個新的字符串以返回。 我試圖提出一個解決方案,也許是在腦海中使用MultiBinding,但無法完全給出答案。

這有可能嗎? 順便說一句,我最終只是創建了被拆分的新屬性,並在設置父對象時對其進行了解析並傳遞了數據。 但是,對我來說,僅使用原始數據和轉換器就可以了,以供將來參考,而無需進行額外的工作。

下面是其他代碼供參考:

XAML,UpsertSkuReference.Quantity是上面的JSON字符串

        <StackPanel Grid.Column="5">
            <TextBlock Text="CBC" />
            <StackPanel Orientation="Horizontal">
                <TextBox Width="30" Text="{Binding UpsertSkuReference.Quantity, ConverterParameter=co, Converter={StaticResource CBCToIndividualConverter}}" IsEnabled="{Binding CBCIsChecked}" />
                <TextBox Width="30" Margin="5,0,0,0" Text="{Binding UpsertSkuReference.Quantity, ConverterParameter=b, Converter={StaticResource CBCToIndividualConverter}}" IsEnabled="{Binding CBCIsChecked}" />
                <TextBox Width="30" Margin="5,0,0,0" Text="{Binding UpsertSkuReference.Quantity, ConverterParameter=ce, Converter={StaticResource CBCToIndividualConverter}}" IsEnabled="{Binding CBCIsChecked}" />
            </StackPanel>
        </StackPanel>

轉換器

public class CBCToIndividualConverter : IValueConverter
{
    JavaScriptSerializer json = new JavaScriptSerializer();

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        //--value = CBC JSON object string
        //--parameter = [co]: Corners, [b]: Borders, [ce]: Centers
        if (value != null)
        {
            if (parameter == null) { throw new Exception("CBCToIndividualConverter: parameter cannot be null"); }
            if (new string[] { "co", "b", "ce" }.Contains(parameter.ToString().ToLower()) == false)
            { throw new Exception("CBCToIndividualConverter: parameter must be 'co' for Corners, 'b' for Borders, or 'ce' for Centers"); }

            CornerBorderCenterModel cbc = json.Deserialize<CornerBorderCenterModel>(value.ToString());

            switch (parameter.ToString().ToLower())
            {
                case "co": { return cbc.Corners; }
                case "b": { return cbc.Borders; }
                case "ce": { return cbc.Centers; }
                default: { return null; }
            }
        }
        else { return null; }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            //--value = number for parameter type
            //--parameter = [co]: Corners, [b]: Borders, [ce]: Centers

            //--?? Uh Oh
        }
        return null;
    }
}

轉換器不應該那樣使用。 有更清潔的方法。 我建議您進行更大的重構:

  • 在包含字符串QuantitySkuReference ?)的類上創建3個屬性: BordersCornersCenters
  • 當您設置其中任何一個時,請更新“ Quantity 在更新Quantity ,您嘗試在CornerBorderCenterModel實例中進行解析,然后使用該實例的值更新3個屬性。 所有這些工作都是在實現OnPropertyChanged方法(請參閱稍后的代碼);
  • 在視圖中,僅將每個TextBox綁定到relative屬性。 這樣,您根本不需要轉換器(如果外部DataContextUpsertSkuReference的實例, UpsertSkuReference ;否則,您必須通過以下方式設置StackPanelDataContextDataContext="{Binding UpsertSkuReference}" ,因此, 3個TextBoxes可以找到對象的屬性。

整個回合:

using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;

namespace XXX
{
    public class CornerBorderCenterModel
    {
        public int Corners { get; set; }
        public int Borders { get; set; }
        public int Centers { get; set; }
    }

    public class SkuReference : INotifyPropertyChanged
    {
        static JavaScriptSerializer json = new JavaScriptSerializer();

        private static string[] _jsonStringParts =
            new[] { nameof(Borders), nameof(Corners), nameof(Centers) };

        public SkuReference()
        {
            PropertyChanged += OnPropertyChanged;
        }

        public int Corners
        {
            get { return _Corners; }
            set
            {
                if (_Corners != value)
                {
                    _Corners = value;
                    RaisePropertyChanged();
                }
            }
        }
        private int _Corners;

        public int Borders
        {
            get { return _Borders; }
            set
            {
                if (_Borders != value)
                {
                    _Borders = value;
                    RaisePropertyChanged();
                }
            }
        }
        private int _Borders;

        public int Centers
        {
            get { return _Centers; }
            set
            {
                if (_Centers != value)
                {
                    _Centers = value;
                    RaisePropertyChanged();
                }
            }
        }
        private int _Centers;

        private void UpdateCBCFromQuantity()
        {
            //if Quantity is a CBC and is not null do the following:

            var cbc = json.Deserialize<CornerBorderCenterModel>(_Quantity.ToString());

            if (cbc != null)
            {
                Corners = cbc.Corners;
                Borders = cbc.Borders;
                Centers = cbc.Centers;
            }
        }

        public string Quantity
        {
            get { return _Quantity; }
            set
            {
                if (_Quantity != value)
                {
                    _Quantity = value;
                    RaisePropertyChanged();
                }
            }
        }
        private string _Quantity;

        private void UpdateJsonStringFromCBC()
        {
            Quantity = string.Format(
                "{{ 'Corners': {0}, 'Borders': {1}, 'Centers': {2} }}",
                _Corners,
                _Borders,
                _Centers);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;

            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (_jsonStringParts.Contains(e.PropertyName))
                UpdateJsonStringFromCBC();

            else if (e.PropertyName == nameof(Quantity))
                UpdateCBCFromQuantity();
        }
    }
}


<StackPanel Orientation="Horizontal" DataContext="{Binding UpsertSkuReference}">
  <TextBox Text="{Binding Corners}" IsEnabled="{Binding CBCIsChecked}" />
  <TextBox Text="{Binding Borders}" IsEnabled="{Binding CBCIsChecked}" />
  <TextBox Text="{Binding Centers}" IsEnabled="{Binding CBCIsChecked}" />
</StackPanel>

請注意, QuantityBordersCornersCenters在更改時必須發出通知(就像我所做的那樣,或者使用諸如Reactive庫之類的更高級的工具),否則整個回合將無法進行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM