2016-04-13 50 views
2

我試圖從Extended WPF Toolkit中重新設置DateTimePicker的控制模板。下面是什麼應該看起來像一個畫面:
Style Comparison帶有現有零件的Restyle控制模板

這裏的原代碼的相關部分:

DateTimePicker.cs

[TemplatePart(Name = PART_Calendar, Type = typeof(Calendar))] 
[TemplatePart(Name = PART_TimeUpDown, Type = typeof(TimePicker))] 
public class DateTimePicker : DateTimePickerBase 
{ 
    private const string PART_Calendar = "PART_Calendar"; 
    private const string PART_TimeUpDown = "PART_TimeUpDown"; 

    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 

     if(_calendar != null) 
      _calendar.SelectedDatesChanged -= Calendar_SelectedDatesChanged; 

     _calendar = GetTemplateChild(PART_Calendar) as Calendar; 

     if(_calendar != null) 
     { 
      _calendar.SelectedDatesChanged += Calendar_SelectedDatesChanged; 
      _calendar.SelectedDate = Value ?? null; 
      _calendar.DisplayDate = Value ?? this.ContextNow; 
      this.SetBlackOutDates(); 
     } 

     _timePicker = GetTemplateChild(PART_TimeUpDown) as TimePicker; 
    } 
} 

Generic.xaml

<Style TargetType="{x:Type local:DateTimePicker}"> 
    ... 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type local:DateTimePicker}"> 
     ... 
     <StackPanel> 
      <Calendar x:Name="PART_Calendar" BorderThickness="0" /> 
      <local:TimePicker x:Name="PART_TimeUpDown" ... /> 
     </StackPanel> 
     ... 
     </ControlTemplate> 
    </Setter.Value> 
    <Setter> 
</Style> 

現在因爲DateTimePicker在後面的代碼中有一些相當不錯的邏輯,用於調整某些事件日曆部分的屬性,我不想重新發明輪子。理想情況下,我想能夠簡單地restyle這樣的控制:

CustomStyles.xaml

<Style x:Key="MetroDateTimePicker" TargetType="{x:Type xctk:DateTimePicker}"> 
    <Setter Property="Foreground" Value="{DynamicResource TextBrush}"/> 
    <Setter Property="Background" Value="{DynamicResource ControlBackgroundBrush}"/> 
    <Setter Property="BorderThickness" Value="1"/> 
    <Setter Property="BorderBrush" Value="{DynamicResource TextBoxBorderBrush}"/> 
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
    <Setter Property="FontFamily" Value="{DynamicResource ContentFontFamily}"/> 
    <Setter Property="FontSize" Value="{DynamicResource ContentFontSize}"/> 
    <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> 
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type xctk:DateTimePicker}"> 
       <Grid> 
        <Border x:Name="Base" 
          Background="{TemplateBinding Background}" 
          BorderBrush="{TemplateBinding BorderBrush}" 
          BorderThickness="{TemplateBinding BorderThickness}" 
          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
        <Grid Margin="5"> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="*" /> 
          <ColumnDefinition Width="Auto" /> 
         </Grid.ColumnDefinitions> 
         <xctk:ButtonSpinner x:Name="PART_Spinner" 
              Grid.Column="0" 
              BorderThickness="0" 
              IsTabStop="False" 
              Background="Transparent" 
              Style="{StaticResource MetroButtonSpinner}" 
              AllowSpin="{TemplateBinding AllowSpin}" 
              ShowButtonSpinner="{TemplateBinding ShowButtonSpinner}"> 
          <xctk:WatermarkTextBox x:Name="PART_TextBox" 
                BorderThickness="0" 
                Background="Transparent" 
                FontFamily="{TemplateBinding FontFamily}" 
                FontSize="{TemplateBinding FontSize}" 
                FontStretch="{TemplateBinding FontStretch}" 
                FontStyle="{TemplateBinding FontStyle}" 
                FontWeight="{TemplateBinding FontWeight}" 
                Foreground="{TemplateBinding Foreground}" 
                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}" 
                MinWidth="20" 
                AcceptsReturn="False" 
                Padding="0" 
                TextAlignment="{TemplateBinding TextAlignment}" 
                TextWrapping="NoWrap" 
                Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}" 
                TabIndex="{TemplateBinding TabIndex}" 
                Watermark="{TemplateBinding Watermark}" 
                WatermarkTemplate="{TemplateBinding WatermarkTemplate}" /> 
         </xctk:ButtonSpinner> 
         <ToggleButton x:Name="_calendarToggleButton" 
             Background="{TemplateBinding Background}" 
             Grid.Column="1" 
             IsChecked="{Binding IsOpen, RelativeSource={RelativeSource TemplatedParent}}" 
             Style="{DynamicResource ChromelessButtonStyle}" 
             Foreground="{TemplateBinding Foreground}" 
             IsTabStop="False"> 
          <Path Fill="{TemplateBinding Foreground}" 
            Data="..." 
            Stretch="Uniform"> 
           <Path.Width> 
            <Binding RelativeSource="{RelativeSource TemplatedParent}" 
              Path="FontSize" 
              Converter="{x:Static shared:FontSizeOffsetConverter.Instance}"> 
             <Binding.ConverterParameter> 
              <sys:Double>4</sys:Double> 
             </Binding.ConverterParameter> 
            </Binding> 
           </Path.Width> 
           <Path.Height> 
            <Binding RelativeSource="{RelativeSource TemplatedParent}" 
              Path="FontSize" 
              Converter="{x:Static shared:FontSizeOffsetConverter.Instance}"> 
             <Binding.ConverterParameter> 
              <sys:Double>4</sys:Double> 
             </Binding.ConverterParameter> 
            </Binding> 
           </Path.Height> 
          </Path> 
         </ToggleButton> 
        </Grid> 
        <Popup x:Name="PART_Popup" 
          AllowsTransparency="True" 
          IsOpen="{Binding IsChecked, ElementName=_calendarToggleButton}" 
          PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" 
          StaysOpen="False"> 
         <Border Padding="3" 
           Background="{DynamicResource WhiteBrush}" 
           BorderBrush="{DynamicResource ComboBoxPopupBrush}" 
           BorderThickness="{TemplateBinding BorderThickness}" 
           Effect="{DynamicResource DropShadowBrush}"> 
          <StackPanel> 
           <Calendar x:Name="Part_Calendar" 
              BorderThickness="0" 
              MinWidth="115" 
              DisplayDateStart="{Binding Minimum, RelativeSource={RelativeSource TemplatedParent}}" 
              DisplayDateEnd="{Binding Maximum, RelativeSource={RelativeSource TemplatedParent}}" 
              IsTodayHighlighted="False"/> 
           <xctk:TimePicker x:Name="PART_TimeUpDown" 
               Style="{StaticResource MetroTimePicker}" 
               Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" 
               Foreground="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" 
               Format="{TemplateBinding TimeFormat}" 
               FormatString="{TemplateBinding TimeFormatString}" 
               Value="{Binding Value, RelativeSource={RelativeSource TemplatedParent}}" 
               Minimum="{Binding Minimum, RelativeSource={RelativeSource TemplatedParent}}" 
               Maximum="{Binding Maximum, RelativeSource={RelativeSource TemplatedParent}}" 
               ClipValueToMinMax="{Binding ClipValueToMinMax, RelativeSource={RelativeSource TemplatedParent}}" 
               IsUndoEnabled="{Binding IsUndoEnabled, RelativeSource={RelativeSource TemplatedParent}}" 
               AllowSpin="{TemplateBinding TimePickerAllowSpin}" 
               ShowButtonSpinner="{TemplateBinding TimePickerShowButtonSpinner}" 
               Watermark="{TemplateBinding TimeWatermark}" 
               WatermarkTemplate="{TemplateBinding TimeWatermarkTemplate}" 
               Visibility="{TemplateBinding TimePickerVisibility}" 
               Margin="3 0 3 3"/> 
          </StackPanel> 
         </Border> 
        </Popup> 
       </Grid> 
       <ControlTemplate.Triggers> 
        <MultiDataTrigger> 
         <MultiDataTrigger.Conditions> 
          <Condition Binding="{Binding IsReadOnly, RelativeSource={RelativeSource Self}}" Value="False" /> 
          <Condition Binding="{Binding AllowTextInput, RelativeSource={RelativeSource Self}}" Value="False" /> 
         </MultiDataTrigger.Conditions> 
         <Setter Property="IsReadOnly" Value="True" TargetName="PART_TextBox" /> 
        </MultiDataTrigger> 
        <DataTrigger Binding="{Binding IsReadOnly, RelativeSource={RelativeSource Self}}" Value="True"> 
         <Setter Property="IsReadOnly" Value="True" TargetName="PART_TextBox" /> 
        </DataTrigger> 
        <Trigger Property="IsEnabled" Value="False"> 
         <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" /> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

注:這不是我改變的唯一的事情;實際上有兩種我省略的樣式(MetroTimePickerMetroButtonSpinner)。一切看起來都很不錯,但它並不正確。每當我在我的代碼中設置一個斷點(在調用ApplyTemplate之後)時,我可以看到私有的_calendar字段爲空。直接調用​​也會返回null(這可能在Watch或Immediate窗口中)。

看來,當我應用自定義樣式時,它不再能夠拾取模板中指定的元素。我一定會錯過一些東西,因爲我認爲我可以應用幾乎所有的控件模板,只要所有命名的部分在那裏(並且具有合適的類型)。所以我的問題是,如何將自定義模板應用於WPF控件,並確保與其命名組件的任何邏輯繼續按預期工作?

+0

這是一個非常特殊的特別場景。除非你有一些特定的共享異常信息/錯誤,這可能有助於演繹推理的整個排序進行故障排除,否則需要專門研究這件事情? –

+0

@ChrisW。對不起,我現在一直在圍繞這個問題困擾我的大腦。完整的風格非常大(實際上涉及3種不同的風格),所以我不想在這裏介入太多。然而,我認爲核心問題是'_calendar'字段爲空,我想不出任何會發生的原因,因爲我的樣式的整體結構實際上與原始樣式非常相似。沒有例外。 –

+0

...並且您確定您正在使用所有PART_ * s?看到一切都可能有所幫助,打賭它是覆蓋控制模板的一些細微的細節。 –

回答

0

好的,我是個白癡。我不知道我多久看這個,雙和三重檢查每一個名字,但不知何故,我從來沒有看到這個愚蠢的小錯字:

<Calendar x:Name="Part_Calendar" … /> 

本來應該是:

<Calendar x:Name="PART_Calendar" … />