我有一个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" />
如何在视图中设置绑定,而不是在样式的定义中。这样我可以在具有不同绑定的多个视图中使用该控件吗?
答案 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的参数,因此您可以在指定命令的地方使用它。