有没有一种方法可以从RadDatePicker中更新视图模型而无需聚焦?

时间:2019-01-22 09:56:03

标签: c# wpf visual-studio rad-controls

我有一个RadDatePicker。以下代码中的NoDotRadDatePicker继承自RadDateTimePicker

当我从控件中选择一个日期时,它将按预期工作并更新view属性。但是,当我编辑与选择器关联的文本框时,它不会对模型进行任何更改。

试图将UpdateSourceTrigger更改为propertychange,但没有帮助

<controls:NoDotRadDatePicker Grid.Row="0"  HorizontalAlignment="Left"
                             Grid.Column="1" MaxWidth="120"
                             SelectedValue="{Binding Path=ValidFrom, ValidatesOnDataErrors=True, UpdateSourceTrigger=Default, Mode=TwoWay}"
                             Style="{StaticResource NoDotDatePickerRightWatermarkContent}" />


public class NoDotRadDatePicker : RadDateTimePicker
{
    public NoDotRadDatePicker()
    {
        this.InputMode = InputMode.DatePicker;
        this.ParseDateTimeValue += RadDateTimePicker_OnParseDateTimeValue;
        this.Culture = new CultureInfo("de-DE");
        this.Culture.DateTimeFormat.ShortDatePattern = "dd.MM.yyyy";
        this.Culture.DateTimeFormat.DateSeparator = ".";
        this.Loaded += NoDotRadDatePicker_Loaded;
    }

    private void RadDateTimePicker_OnParseDateTimeValue(object sender, ParseDateTimeEventArgs args)
    {
        const int firstDayInMonth = 1;
        const int firstMonth = 1;
        string input = args.TextToParse.ToLower();

        if (!ContainsOnlyDigitsAndDot(input))
        {
            args.IsParsingSuccessful = false;
            return;
        }
        int day = firstDayInMonth;
        int month = firstMonth;
        int year = DateTime.Now.Year;

        if (!SplitDateTime2Parts(input, ref day, ref month, ref year))
        {
            args.IsParsingSuccessful = false;
            return;
        }

        args.Result = new DateTime(year, month, day);
        args.IsParsingSuccessful = true;
    }

    private bool SplitDateTime2Parts(string input, ref int day, ref int month, ref int year)
    {
        int k = 0;
        var partOfYearCounter = DateTimeParts.Day;

        string parsePart = "";
        foreach (char t in input)
        {
            if (t == '.')
            {
                if (string.IsNullOrEmpty(parsePart)) continue;
                if (!DoTheDayMonthParsing(ref k, ref parsePart, ref day, ref month, ref partOfYearCounter)) return false;
                continue;
            }
            parsePart += t;
            k++;
            if (k != 2 || (partOfYearCounter != DateTimeParts.Day && partOfYearCounter != DateTimeParts.Month)) continue;
            if (!DoTheDayMonthParsing(ref k, ref parsePart, ref day, ref month, ref partOfYearCounter)) return false;
        }

        if (partOfYearCounter == DateTimeParts.Day || partOfYearCounter == DateTimeParts.Month)
            if (!ParseDayOrMonthHelper(partOfYearCounter, parsePart, ref day, ref month)) return false;
        if (partOfYearCounter == DateTimeParts.Year)
            if (!DoTheYearParsing(parsePart, ref year)) return false;
        if (day > DateTime.DaysInMonth(year, month)) return false;

        return true;
    }

    private bool DoTheYearParsing(string parsePart, ref int year)
    {
        if (string.IsNullOrEmpty(parsePart)) return true;

        int parsedYear;
        if (!int.TryParse(parsePart, out parsedYear)) return false;
        year = parsedYear;
        if (year >= 0 && year <= 49) year += 2000;
        if (year >= 50 && year <= 99) year += 1900;
        if (year < 1753 || year > 3000) return false;

        return true;
    }

    private bool DoTheDayMonthParsing(ref int k, 
    ref string parsePart, ref int day, ref int month, 
    ref DateTimeParts partOfYearCounter)
    {
        if (!ParseDayOrMonthHelper(partOfYearCounter, parsePart, ref day, ref month))
            return false;

        if (partOfYearCounter == DateTimeParts.Month) partOfYearCounter = DateTimeParts.Year;
        if (partOfYearCounter == DateTimeParts.Day) partOfYearCounter = DateTimeParts.Month;

        parsePart = "";
        k = 0;
        return true;
    }

    private bool ParseDayOrMonthHelper(DateTimeParts partOfYearCounter, string parsePart, ref int day, ref int month)
    {
        if (string.IsNullOrEmpty(parsePart)) return true;

        switch (partOfYearCounter)
        {
            case DateTimeParts.Day:
                if (!ParseValueHelper(parsePart, ref day, 1, 31)) return false;
                break;
            case DateTimeParts.Month:
                if (!ParseValueHelper(parsePart, ref month, 1, 12)) return false;
                break;
            default:
                return false;
        }
        return true;
    }

    private bool ParseValueHelper(string parsePart, ref int value2StoreIn, int lowBoundary, int highBoundary)
    {
        int parsedValue;
        if (!int.TryParse(parsePart, out parsedValue)) return false;
        if (parsedValue == 0) return true;
        if (parsedValue >= lowBoundary && parsedValue <= highBoundary)
        {
            value2StoreIn = parsedValue;
            return true;
        }
        return false;
    }

    private bool ContainsOnlyDigitsAndDot(string string2BeChecked)
    {
        return string2BeChecked.All(t => char.IsDigit(t) || t == '.');
    }

    enum DateTimeParts
    {
        Day = 1,
        Month = 2,
        Year = 3
    };

    void NoDotRadDatePicker_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        if (this.VisualChildrenCount == 0)
            return;

        var rootElement = VisualTreeHelper.GetChild(sender as RadDateTimePicker, 0) as FrameworkElement;
        RadWatermarkTextBox watermarkTextBlock = (RadWatermarkTextBox)rootElement.FindName("PART_DateTimeInput");

        var contentControl = watermarkTextBlock.ChildrenOfType<ContentControl>().Where(p => p.Name == "WatermarkVisualElement").First();
        if (contentControl != null)
        {
            contentControl.Opacity = 1.0;
            contentControl.Foreground = new SolidColorBrush(Colors.Black); 
            //contentControl.FontStyle = FontStyles.Normal;
        }
    } 
}

0 个答案:

没有答案