WPF - 设置自定义样式的子控件的属性

时间:2017-07-27 11:23:32

标签: c# wpf wpf-style

我有一个SearchTextBox的自定义样式。我在这个控件中有多个Bindings。

<Style TargetType="{x:Type controls:SearchTextBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:SearchTextBox}">
                <Grid>
                    <TextBox Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}">
                        <TextBox.InputBindings>
                            <KeyBinding Command="{Binding Path=SearchCommand}" Key="Enter" />
                            <KeyBinding Command="{Binding Path=DeleteSearchCommand}" Key="Esc" />
                        </TextBox.InputBindings>
                    </TextBox>
                    <Button Style="{StaticResource WatermarkButtonCancelStyle}" HorizontalAlignment="Right" Command="{Binding DeleteSearchCommand}" Margin="0,0,22,0"/>
                    <Button Style="{StaticResource WatermarkButtonSearchStyle}" HorizontalAlignment="Right" Command="{Binding SearchCommand}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我在我的视图中使用TextBox:

<controls:SearchTextBox Width="300" HorizontalAlignment="Left" Margin="0,0,0,6" />

如何在视图中设置绑定,而不是在样式的定义中。这样我可以在具有不同绑定的多个视图中使用该控件吗?

1 个答案:

答案 0 :(得分:0)

自定义TextBox的样式:

Option Explicit
Public Sub GenerateResults()
    Dim arr As Variant, tmp As Variant, Dates() As Double, Results As Object
    Dim i As Long, j As Long, StartRow As Long, ResultsSeparator As Long
    Dim StartYear As Long, EndYear As Long, yr As Long, mo As Long
    Dim c

    ' ******UPDATE TO POINT AT YOUR ARRAY******
    With Sheet1
        arr = Range(.Cells(1, 1), .Cells(4, 5)).Value2
    End With

    Set Results = CreateObject("Scripting.Dictionary")

    For j = 3 To UBound(arr, 2)
        If StartYear < Format(WorksheetFunction.Min(Application.Index(arr, 0, j)), "yyyy") Then
             StartYear = Format(WorksheetFunction.Min(Application.Index(arr, 0, j)), "yyyy")
        End If
        If EndYear < Format(WorksheetFunction.Max(Application.Index(arr, 0, j)), "yyyy") Then
            EndYear = Format(WorksheetFunction.Max(Application.Index(arr, 0, j)), "yyyy")
        End If
    Next j

    ' 1 to 12 for months in the year, 1 to 2 for each activitity. This could be adapated for more then 12 months
    ReDim Dates(1 To (1 + EndYear - StartYear) * 12, 1 To UBound(arr, 2) - 2)

    For i = LBound(arr) To UBound(arr)
        Set tmp = Nothing
        ' Add to dictionary if colour not in array
        If Not Results.exists(arr(i, 2)) Then Results.Add Key:=arr(i, 2), Item:=Dates
        ' Assign your data to a temporary array so we can change it
        tmp = Results(arr(i, 2))
        ' Update data with activity dates
        For j = LBound(Dates, 2) To UBound(Dates, 2)
            tmp(12 * (Year(arr(i, 2 + j)) - StartYear) + Month(arr(i, 2 + j)), j) = tmp(12 * (Year(arr(i, 2 + j)) - StartYear) + Month(arr(i, 2 + j)), j) + 1
        Next j
        ' Write data back to dictionary
        Results(arr(i, 2)) = tmp
    Next i

    Application.ScreenUpdating = False
    ' ******CHANGE TO WHERE YOUR WANT YOUR RESULTS******
    ' Starting row of results (change to your output)
    StartRow = 7
    ' How many rows do you want between Activity A and B etc.
    ResultsSeparator = 3

    With Sheet1
        For j = LBound(Dates, 2) To UBound(Dates, 2)
            With .Cells(StartRow + (j - 1) * (ResultsSeparator + Results.Count), 1)
                .Value2 = UCase("Activity " & Split(.Cells(1, j).Address, "$")(1))
                .Font.Bold = True
            End With
        Next j
        StartRow = StartRow + 1
        For j = LBound(Dates, 1) To UBound(Dates, 1)
            yr = StartYear + IIf(j Mod 12 = 0, (j / 12) - 1, WorksheetFunction.RoundDown(j / 12, 0))
            mo = IIf(j > 12, j - 12 * IIf(j Mod 12 = 0, (j / 12) - 1, WorksheetFunction.RoundDown(j / 12, 0)), j)
            For i = LBound(Dates, 2) To UBound(Dates, 2)
                With .Cells(StartRow + (i - 1) * (ResultsSeparator + Results.Count), 1 + j)
                    .Value2 = DateSerial(yr, mo, 1)
                    .NumberFormat = "mmm-yy"
                End With
            Next i
        Next j
        StartRow = StartRow + 1
        ' Loop through dictionary
        For Each c In Results.keys
            ' Write back results for Activity A
            For j = LBound(Dates, 2) To UBound(Dates, 2)
                With .Cells(StartRow + (j - 1) * (ResultsSeparator + Results.Count), 1)
                    .Value2 = c
                    Range(.Offset(0, 1), .Offset(0, UBound(Results(c), 1))) = Application.Transpose(Application.Index(Results(c), 0, j))
                End With
            Next j
            ' Increase Row
            StartRow = StartRow + 1
        Next c
    End With
    Application.ScreenUpdating = True
End Sub

SearchTextBox.cs的代码:

        <Style TargetType="{x:Type local:SearchTextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:SearchTextBox}">
                    <DockPanel DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:SearchTextBox}}}">
                        <Button DockPanel.Dock="Right"
                                Style="{StaticResource WatermarkButtonCancelStyle}"
                                Command="{Binding DeleteSearchCommand}"/>
                        <Button DockPanel.Dock="Right"
                                Style="{StaticResource WatermarkButtonSearchStyle}"
                                Command="{Binding SearchCommand}"
                                CommandParameter="{Binding Text}"/>
                        <TextBox x:Name="InnerTextBox"
                                 Text="{Binding Path=Text}">
                            <TextBox.InputBindings>
                                <KeyBinding Command="{Binding SearchCommand}"
                                            CommandParameter="{Binding Text}"
                                            Key="Enter" />
                                <KeyBinding Command="{Binding DeleteSearchCommand}"
                                            Key="Escape" />
                            </TextBox.InputBindings>
                        </TextBox>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

由于清除TextBox的命令始终相同,因此SearchTextBox包含用于清除它的命令。

现在可以在View中使用SearchTextBox,只需设置public class SearchTextBox : TextBox { public static readonly DependencyProperty SearchCommandProperty = DependencyProperty.Register( "SearchCommand", typeof(ICommand), typeof(SearchTextBox), new PropertyMetadata(default(ICommand))); public SearchTextBox() { DeleteSearchCommand = new Command { ExecuteHandler = o => Clear() }; } public ICommand SearchCommand { get { return (ICommand) GetValue(SearchCommandProperty); } set { SetValue(SearchCommandProperty, value); } } public Command DeleteSearchCommand { get; private set; } } 属性。

SearchCommand

正如您在SearchTextBox的样式中所看到的,Text被设置为SearchCommand的参数,因此您可以在指定命令的地方使用它。