2015-10-23 18 views
1

TimeSpanUpDown (Extended WPF Toolkit), кажется, имеет ошибку отображения, когда количество дней изменяется от 0 до> 0.Обходной способ для отображения ошибки TimeSpanUpDown при смене дней

Вот простой способ, чтобы воспроизвести его:

<Window x:Class="TimeSpanBug.MainWindow" 
     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" 
     Height="100" Width="200"> 
    <StackPanel> 
     <!-- Bind both to the same TimeSpan property in the ViewModel --> 
     <xctk:TimeSpanUpDown Value="{Binding TimeSpan}"/> 
     <xctk:TimeSpanUpDown Value="{Binding TimeSpan}"/> 
    </StackPanel> 
</Window> 

Введите промежуток времени вблизи, но ниже 24ч. Количество дней автоматически скрывается.

enter image description here

Затем нажмите стрелку вверх на первый элемент управления, чтобы увеличить промежуток времени до> 24h. Теперь элемент управления обновляет его отображение, чтобы включить количество дней. Второй элемент управления получает свойство измененного уведомления, а также пытается обновить, но в конечном итоге в странное состояние:

enter image description here

Очевидно, что это является ошибкой и должен быть закреплен на Xceed, но кто-нибудь знает быстрый и легко исправить или обходной путь?

+0

@jstreet Извините, сейчас я работаю над другим проектом. Я буду пересматривать этот вопрос когда-нибудь в будущем ... –

ответ

0

Почему бы вам не свернуть? Добро пожаловать в создание пользовательского контроля! Простая отправная точка без вышеуказанной ошибки, которые вы можете настроить к содержанию вашего сердца:

[TemplatePart(Name = "UP", Type = typeof(ButtonBase))] 
[TemplatePart(Name = "DOWN", Type = typeof(ButtonBase))] 
public class TimeSpinner : Control 
{ 
    static TimeSpinner() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(TimeSpinner), new FrameworkPropertyMetadata(typeof(TimeSpinner))); 
    } 

    public TimeSpan Time 
    { 
     get { return (TimeSpan)GetValue(TimeProperty); } 
     set { SetValue(TimeProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Time. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty TimeProperty = 
     DependencyProperty.Register("Time", typeof(TimeSpan), typeof(TimeSpinner), new PropertyMetadata(TimeSpan.Zero)); 

    public TimeSpan Interval 
    { 
     get { return (TimeSpan)GetValue(IntervalProperty); } 
     set { SetValue(IntervalProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Interval. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty IntervalProperty = 
     DependencyProperty.Register("Interval", typeof(TimeSpan), typeof(TimeSpinner), new PropertyMetadata(TimeSpan.FromTicks(TimeSpan.TicksPerHour))); 

    private static readonly TimeSpan OneDay = TimeSpan.FromTicks(TimeSpan.TicksPerDay); 

    void UpTime() 
    { 
     var newTime = Time + Interval; 
     if (newTime >= OneDay) 
      Time = newTime - OneDay; 
     else 
      Time = newTime; 
    } 

    void DownTime() 
    { 
     var newTime = Time - Interval; 
     if (newTime < TimeSpan.Zero) 
      Time = newTime + OneDay; 
     else 
      Time = newTime; 
    } 


    public override void OnApplyTemplate() 
    { 
     var upButton = GetUIPart<ButtonBase>("UP"); 
     if(upButton != null) 
      upButton.Click += upButton_Click; 
     if (_upButton != null) 
      _upButton.Click -= upButton_Click; 
     _upButton = upButton; 

     var downButton = GetUIPart<ButtonBase>("DOWN"); 
     if (downButton != null) 
      downButton.Click += downButton_Click; 
     if (_downButton != null) 
      _downButton.Click -= downButton_Click; 
     _downButton = downButton; 
    } 

    void downButton_Click(object sender, RoutedEventArgs e) 
    { 
     DownTime(); 
    } 

    void upButton_Click(object sender, RoutedEventArgs e) 
    { 
     UpTime(); 
    } 

    private ButtonBase _upButton; 
    private ButtonBase _downButton; 

    T GetUIPart<T>(string name) where T : DependencyObject 
    { 
     return (T) GetTemplateChild(name); 
    } 
} 

и шаблону образца (который должен поставить в ResourceDictionary под названием Generic.xaml в папке Themes в корне вашего проект):

<Style TargetType="{x:Type local:TimeSpinner}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:TimeSpinner}"> 
       <Border Background="{TemplateBinding Background}" 
         BorderBrush="{TemplateBinding BorderBrush}" 
         BorderThickness="{TemplateBinding BorderThickness}"> 
        <DockPanel> 
         <UniformGrid Columns="1" DockPanel.Dock="Right"> 
          <Button x:Name="UP" Content="+"/> 
          <Button x:Name="DOWN" Content="-"/> 
         </UniformGrid> 
         <TextBox Text="{Binding Time, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/> 
        </DockPanel> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 
+0

Почему бы вам не катиться? Потому что это занимает много времени. Я не собираюсь переопределять все функции TimeSpanUpDown только из-за небольшой ошибки, которая появляется в случае с редким краем. Извините, но это не совсем ответ на мой вопрос. –

+1

Ну, это заняло около 10 минут, чтобы собрать - сколько функций вы могли бы захотеть в прядильщике? Я думаю, что если вы посмотрите на управление авторством, вы обнаружите, что это не черная магия, и вы узнаете много о WPF от нее * и *, что вы можете иметь именно то, что хотите, но этот тип управления про самую простую вещь, которую вы можете сделать. Ну что ж. –

Смежные вопросы