3

WPF CustomControlを実装したいのですが、...

  1. 通常はボタンのように見え、float値を文字列として表示します
  2. ボタンをドラッグすると、フロート値が仮想スライダーのように操作されます
  3. ボタンをクリックすると、現在の値が文字列として事前に入力されたテキストボックスに置き換えられます。このテキストは編集できます。TextBoxの外側をクリックするか、Returnキーを押すと、コントロールがButtonに戻り、編集したテキストが新しい値として使用されます。

高度に合理化されたインターフェースでこの制御が必要です。説明は少し奇妙に聞こえますが、私たちにとっては驚くほどうまく機能します。ただし、パフォーマンス上の理由から、現在の実装をUserControlとしてCustomControlにリファクタリングする必要があります。

コントロールのスライダー部分を実行し、ContentDependencyPropertyにアタッチされたTextBoxを表示することができました。ただし、残念ながら、ControlTemplateからこのTextBoxにアクセスできません。これは、おおよそ次のようになります。

<Style TargetType="{x:Type local:FloatEditButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:FloatEditButton}">
                <Grid Margin="0">
                    <Viewbox VerticalAlignment="Center" HorizontalAlignment="{Binding RelativeSource={RelativeSource TemplatedParent},Path=HorizontalContentAlignment}" Margin="0">
                        <ContentPresenter Name="content" Margin="2"  VerticalAlignment="Center" />
                    </Viewbox>
                    <TextBox  x:Name="XTextBox" Visibility="Collapsed" Text="{Binding Content}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="EditingAsTextBox" Value="True">
                        <Setter TargetName="XTextBox" Property="Visibility" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

これをCustomControlとして実装する方法はありますか?

4

2 に答える 2

0

少しいじった後、私は次の解決策を見つけました:

Generic.xamlのテンプレートは次のようになります...

<Style TargetType="{x:Type local:FloatEditButton}">        
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:FloatEditButton}">
                <Grid Margin="0">
                    <TextBlock x:Name="PART_TextBlock" Grid.Row="1"
                               VerticalAlignment="Center" 
                               HorizontalAlignment="Center"
                               Margin="0"
                               FontSize="{TemplateBinding FontSize}"                                   
                               ></TextBlock>
                    <Canvas x:Name="SliderCanvas" Grid.Row="1"  IsHitTestVisible="False" Margin="0,3,0,2">
                        <Rectangle x:Name="PART_SliderDefaultRectangle" Width="1" Height="3" Canvas.Bottom="0"  Fill="Black"/>
                        <Rectangle x:Name="PART_SliderMarkerRectangle" Width="1" Canvas.Top="0" Canvas.Left="20" Fill="#30ffffff" Height="{Binding ElementName=SliderCanvas, Path=ActualHeight}" />
                        <Rectangle x:Name="PART_SliderFillRectangle" Width="10"  Fill="#10ffffff" Height="{Binding ElementName=SliderCanvas, Path=ActualHeight}"  />
                    </Canvas>
                    <TextBox  x:Name="PART_TextBox" 
                              Visibility="Collapsed" 
                              FontSize="{TemplateBinding FontSize}"                                   
                              VerticalAlignment="Center" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

イニシャライザ関数はおおまかに次のようになります。重要な部分は、OnApplyTemplateを上書きし、GetTemplateChild()を使用することです。

/**
 * Since we're using a CostumControl, we need to get the relevant UI children for the current instance
 * for changing their properties later and assigning eventhandlers.
 */
public override void OnApplyTemplate() {
    base.OnApplyTemplate();
    _textBox = GetTemplateChild("PART_TextBox") as TextBox;  // NOTE: FindName("PART_TextBox");  does NOT work here

    MouseLeftButtonDown+= MouseLeftButtonDownHandler;
    MouseLeftButtonUp+= MouseLeftButtonUpHandler;
    MouseMove+= MouseMoveHandler;
    MouseWheel+= MouseWheelHandler;
    LayoutUpdated+=LayoutUpdatedHandler;

    if (_textBox !=null) {
        _textBox.TextChanged += TextChangedHandler;
        _textBox.KeyUp += KeyUpHandler;
        _textBox.LostFocus += LostFocusHandler;
    }

    _sliderFillRectangle =    GetTemplateChild("PART_SliderFillRectangle") as Rectangle;
    _sliderDefaultRectangle = GetTemplateChild("PART_SliderDefaultRectangle") as Rectangle;
    _sliderMarkerRectangle =  GetTemplateChild("PART_SliderMarkerRectangle") as Rectangle;
    _textBlock = GetTemplateChild("PART_TextBlock") as TextBlock;
}

内部メンバー変数は、後で次のように使用されます...

private void LostFocusHandler(object sender, RoutedEventArgs e) {
    if (!UpdateValueFromTextEdit())
        _textBox.Text = Value.ToString();

    _textBox.Visibility = Visibility.Collapsed;
    e.Handled= true;
}

UserControlからCustomControlへのリファクタリングにより、インスタンス化が50%高速化されます。

于 2012-05-26T22:26:17.750 に答える