2012-03-14 66 views
0

因此,我很難理解這一點。我有一個自定義控件,使用向上/向下按鈕來增加/減少切換按鈕上顯示的時間。我有切換的Content屬性顯示HourMinute屬性的正確值,我正在嘗試設置代碼隱藏以增加值。根據VS2010調試器,它增加Hour屬性的值,但它不改變Toggles的內容來反映這一點。我將綁定模式設置爲TwoWay,並且我使用{綁定RelativeSource={RelativeSource TemplatedParent}, Path=Hour, Mode=TwoWay}綁定到該值,因爲它位於自定義控件的generic.xaml文件中。關於如何使顯示值正確更新的任何想法?使用依賴項屬性的數字UpDown控件

XAML:(樣式模板刪除以節省空間)

<Style TargetType="{x:Type local:TimePicker}"> 
    <Setter Property="Height" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height}" /> 
    <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}" /> 
    <Setter Property="HorizontalAlignment" Value="Center" /> 
    <Setter Property="VerticalAlignment" Value="Center" /> 
    <Setter Property="FontSize" Value="14" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate> 
       <Border Background="{TemplateBinding Background}" 
         BorderBrush="Transparent" 
         BorderThickness="1"> 
        <StackPanel x:Name="PART_Root" 
           Orientation="Horizontal" 
           HorizontalAlignment="Center" 
           VerticalAlignment="{TemplateBinding VerticalAlignment}"> 
         <!--Region Hour Button--> 
         <ToggleButton x:Name="PART_Hour" 
             VerticalAlignment="{TemplateBinding VerticalAlignment}" 
             Margin="0" 
             BorderBrush="Transparent" 
             BorderThickness="0" 
             Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Hour, Mode=TwoWay, BindsDirectlyToSource=True}">         
         </ToggleButton> 
         <!--EndRegion--> 
         <Label HorizontalContentAlignment="{TemplateBinding HorizontalAlignment}" 
           VerticalContentAlignment="{TemplateBinding VerticalAlignment}" 
           FontSize="14" 
           Content=":"/> 
         <!--Region Minute Button--> 
         <ToggleButton x:Name="PART_Minute" 
             VerticalAlignment="{TemplateBinding VerticalAlignment}" 
             Margin="0" 
             BorderBrush="Transparent" 
             Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Minute}">         
         </ToggleButton> 
         <!--EndRegion--> 
         <StackPanel x:Name="PART_IncDecPanel" 
            HorizontalAlignment="Center" 
            VerticalAlignment="Center" 
            Orientation="Vertical"> 
          <Grid Height="{Binding ElementName=PART_Hour, Path=ActualHeight}"> 
           <Grid.RowDefinitions> 
            <RowDefinition Height="*"/> 
            <RowDefinition Height="*"/> 
           </Grid.RowDefinitions> 
           <Viewbox Stretch="Fill" Grid.Row="0"> 
            <!--Region Increase Button--> 
            <Button x:Name="PART_IncreaseTime" 
              HorizontalContentAlignment="{TemplateBinding HorizontalAlignment}" 
              VerticalContentAlignment="{TemplateBinding VerticalAlignment}" 
              BorderBrush="Transparent" 
              BorderThickness="0" 
              FontFamily="Marlett" 
              Foreground="DimGray" 
              Content="5" 
              Padding="0" 
              Click="PART_IncreaseTime_Click">            
            </Button> 
            <!--EndRegion--> 
           </Viewbox > 
           <Viewbox Stretch="Fill" Grid.Row="1"> 
            <!--Region Decrease Button--> 
            <Button x:Name="PART_DecreaseTime" 
              HorizontalContentAlignment="{TemplateBinding HorizontalAlignment}" 
              VerticalContentAlignment="{TemplateBinding VerticalAlignment}" 
              BorderBrush="Transparent" 
              BorderThickness="0" 
              FontFamily="Marlett" 
              Foreground="DimGray" 
              Content="6" 
              Padding="0">            
            </Button> 
            <!--EndRegion--> 
           </Viewbox> 
          </Grid> 

         </StackPanel> 

        </StackPanel> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

代碼:

public class TimePicker : Control 
{ 
    #region Dependency Property Declarations 
    public static DependencyProperty HourProperty = DependencyProperty.Register("Hour", typeof(int), typeof(TimePicker), 
     new FrameworkPropertyMetadata((int)12, new PropertyChangedCallback(OnHourChanged))); 

    public static DependencyProperty MinuteProperty = DependencyProperty.Register("Minute", typeof(string), typeof(TimePicker), 
     new FrameworkPropertyMetadata((string)"00", new PropertyChangedCallback(OnMinuteChanged)));   

    #endregion 

    #region Properties 
    public int Hour 
    { 
     get { return (int)GetValue(HourProperty); } 
     set { SetValue(HourProperty, value); } 
    } 

    public string Minute 
    { 
     get { return (string)GetValue(MinuteProperty); } 
     set { SetValue(MinuteProperty, value); } 
    } 
    #endregion 

    #region Events 
    private static void OnHourChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     TimePicker time = new TimePicker(); 
     time.Hour = (int)e.NewValue; 
     MessageBox.Show("Hour changed"); 
    } 

    private static void OnMinuteChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 

    } 
    #endregion 

    static TimePicker() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(TimePicker), new FrameworkPropertyMetadata(typeof(TimePicker))); 
    } 
} 

public partial class TimePickerEvents : ResourceDictionary 
{ 
    TimePicker time = new TimePicker(); 

    void PART_IncreaseTime_Click(object sender, RoutedEventArgs e) 
    { 
     time.Hour += 1; 

    } 
} 
+0

你爲什麼要在OnHourChanged中創建一個新的TimerPicker? – 2012-03-14 14:36:48

+0

這是我可以訪問'Hour'而不是'HourProperty'的唯一方法。 – 2012-03-14 14:45:25

+0

'TimePicker timePicker =(TimePicker)發件人;' – 2012-03-14 14:49:19

回答

1

不知道你爲什麼使用一個Togglebutton來顯示小時/分鐘,我認爲一個Label/TextBlock會更適合這個。

更改您的ToggleButtons的結合

Content="{TemplateBinding Hour}" 

然後在代碼,重寫OnApplyTemplate這樣

public override void OnApplyTemplate() 
{ 
    var upButton = GetTemplateChild("PART_IncreaseTime") as Button; 
    upButton.Click += IncreaseClick; 

    var downButton = GetTemplateChild("PART_DecreaseTime") as Button; 
    downButton.Click += DecreaseClick; 
} 

private void IncreaseClick(object sender, RoutedEventArgs e) 
{ 
    // Here would be a place to see what toggle button is checked 
    // (or which TextBlock last had focus) and increase Hour/Minute 
    // based on that info 
    Hour += 1; 
} 

private void DecreaseClick(object sender, RoutedEventArgs e) 
{ 
    // Here would be a place to see what toggle button is checked 
    // (or which TextBlock last had focus) and decreaseHour/Minute 
    // based on that info 
    Hour -= 1; 
} 

這應該讓你開始。 供參考:在您的OnHourChanged和OnMinuteChanged中,發件人是您的控件(TimePicker)。因此,您可以將發件人轉換爲TimePicker並訪問您的所有屬性。即使你的私人財產。

+0

使用ToggleButton背後的邏輯是它帶有內置的保持選中狀態的能力,而Label沒有。至於TextBlock,我真的不想讓光標閃爍,我只是希望它被選中。我確定我可以重寫遊標,但這似乎更自然。我強烈地考慮切換到一個RadioButton作爲基地,但我想先讓它工作。 :)我確實嘗試了你的建議,並且在將GetTemplatePart改爲GetTemplateChild後,它工作。謝謝! – 2012-03-14 16:03:59

+0

Woops,對於Typo感到抱歉。我改成了正確的方法名稱。我可以向你保證,客戶想要手動更改時間以及上/下。這就是TextBox最好的原因。然後,您可以使用Tab鍵在您的控件中進行選項卡設置,並使用Up/Down按鈕或使用滾輪或上/下鍵盤按鍵。現在開始考慮這些。 – 2012-03-14 18:49:48

0

你爲什麼不使用WPF工具包的數值上下控制? http://wpftoolkit.codeplex.com/wikipage?title=NumericUpDown

所有你需要做的就是將它綁定到你的屬性兩種方式。

+0

這應該是一個評論,因爲你不幫他.. – 2012-03-14 14:33:21

+0

主要是因爲這是我學習自定義控件的機會,也因爲我真的不是粉絲重用其他內容。我會從其他來源獲取想法,但我喜歡自己提供的挑戰和學習機會。 – 2012-03-14 14:44:09