MaskedTextBox не показывает значение - PullRequest
0 голосов
/ 21 марта 2019

Вот мой сценарий:

У меня есть DataGrid с двумя столбцами, представляющими широту и долготу.ItemsSource связан с коллекцией класса модели CustomVertex, которая содержит два свойства: X и Y, которые double с.

У меня есть три формата, в которых эти значения могут быть: Десятичные градусы, градусы, минуты и градусы, минуты, секунды.У меня есть три RadioButtons, соответствующих этим, и в зависимости от того, какой из них выбран, он изменит значение ячеек DataGrid на правильный формат через конвертер.

Я использую Xceed's MaskedTextBox в ячейках DataGrid, и я связал свойство Mask со строковым свойством в моем ViewModel, чтобы изменить Mask при каждом изменении формата.Это меняет маску, за исключением того, что она очищает любые значения от самого MaskedTextBox вместо их преобразования.Любой пользовательский ввод в MaskedTextBox тоже ничего не вызывает.

Во-первых, вот модель CustomVertex:

public class CustomVertex : ValidatableModel
{
    /// <summary>
    /// Represents the X-Coordinate (Longitude)
    /// </summary>
    private double _x;
    public double X
    {
        get { return _x; }
        set
        {
            if (_x != value)
            {
                _x = value;
                RaisePropertyChanged("X");
            }
        }
    }

    /// <summary>
    /// Represents the Y-Coordinate (Latitude)
    /// </summary>
    private double _y;
    public double Y
    {
        get { return _y; }
        set
        {
            if (_y != value)
            {
                _y = value;
                RaisePropertyChanged("Y");
            }
        }
    }

    public CustomVertex(double latitude, double longitude)
    {
        Y = latitude;
        X = longitude;
    }

    public CustomVertex()
    {
        Y = 0;
        X = 0;
    }
}

Вот DataGrid в .xaml моего окна (здесь отображается только столбец широты, но столбец долготы точно такой же).Я включил RadioButton s, а также просто incase:

<RadioButton Name="degRB" Checked="VertexFormatRB_Checked" IsChecked="{Binding Path=SelectedVertexType, Converter={StaticResource EBConverter}, ConverterParameter={x:Static enums:VertexType.DDD}}" GroupName="UnitType" Content="Deg" />
<RadioButton Name="degMinRB" Checked="VertexFormatRB_Checked" IsChecked="{Binding Path=SelectedVertexType, Converter={StaticResource EBConverter}, ConverterParameter={x:Static enums:VertexType.DDDMM}}" GroupName="UnitType" Content="Deg Min"/>
<RadioButton Name="degMinSecRB" Checked="VertexFormatRB_Checked" IsChecked="{Binding Path=SelectedVertexType, Converter={StaticResource EBConverter}, ConverterParameter={x:Static enums:VertexType.DDDMMSS}}" GroupName="UnitType" Content="Deg Min Sec"/>

<DataGrid ItemsSource="{Binding Vertices}" AutoGenerateColumns="False" IsReadOnly="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Latitude" IsReadOnly="False">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <xctk:MaskedTextBox Mask="{Binding DataContext.Mask, RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
                        <xctk:MaskedTextBox.Text>
                            <MultiBinding Converter="{StaticResource VertexConverter}" UpdateSourceTrigger="Default">
                                <Binding Path="Y" />
                                <Binding Path="DataContext.SelectedVertexType" RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}" />
                            </MultiBinding>
                        </xctk:MaskedTextBox.Text>
                        </xctk:MaskedTextBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Вот VertexConverter, который используется для переключения значения Y в правильный формат.Я оставил некоторые вещи из ConvertBack, но вы должны получить суть:

public sealed class VertexConverter : IMultiValueConverter
{
    private VertexType vertexType = VertexType.DDD;

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values[0] == DependencyProperty.UnsetValue)
        {
            return null;
        }
        if ((VertexType)values[1] == VertexType.DDD)
        {
            vertexType = VertexType.DDD;
            return Math.Round((double)values[0], 9).ToString();
        }
        else if ((VertexType)values[1] == VertexType.DDDMM)
        {
            vertexType = VertexType.DDDMM;
            double dd = Math.Truncate((double)values[0]);
            double mm = Math.Round(((double)values[0] - dd) * 60, 7);
            return dd + "°" + " " + mm + '"';
        }
        else if ((VertexType)values[1] == VertexType.DDDMMSS)
        {
            vertexType = VertexType.DDDMMSS;
            return DecimalDegreesHelper.GetDegreesMinutesSecondsFromDecimalDegree((double)values[0]).ToString();
        }
        else
        {
            return "";
        }
    }


    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        object[] ret = new object[2];
        if (vertexType == VertexType.DDD)
        {
            ret[0] = double.Parse(value.ToString());
            ret[1] = vertexType;
        }
        else if (vertexType == VertexType.DDDMM)
        {
            //more stuff
        }
        else
        {
            //more stuff
        }
        return ret;
    }
}

Наконец, необходимые части ViewModel:

const string DDD_MASK = "####.#########"; //ex: -170.112233440
const string DDDMM_MASK = ""; //todo
const string DDDMMSS_MASK = ""; //todo

public ObservableCollection<CustomVertex> Vertices { get; set; } //DataGrid is bound to this. Set to new collection in vm's constructor

private VertexType _selectedVertexType;
public VertexType SelectedVertexType
{
    get => _selectedVertexType;
    set
    {
        _selectedVertexType = value;
        if (value == VertexType.DDD)
        {
            Mask = DDD_MASK;
        }
        else if (value == VertexType.DDDMM)
        {
            Mask = DDDMM_MASK;
        }
        else if (value == VertexType.DDDMMSS)
        {
            Mask = DDDMMSS_MASK;
        }
        OnPropertyChanged();
    }
}

public string Mask { get; set; }

И сам перечислитель:

public enum VertexType
{
    DDD,
    DDDMM,
    DDDMMSS
}

Я пытался извлечь значение Mask из ViewModel и использовать другое Converter для свойства Mask, но это вывело ту же ошибку.

Сторона-примечание - если это не лучший способ заставить правильный ввод пользователя, я открыт для других идей.

...