我已經爲我的問題創建了一個很好的解決方案。下面的代碼顯示了我實現:
// KeyboardButton.cs
/// <remarks>
/// This class does contain a lot of more code which isn't related to the actual problem.
/// </remarks>
public partial class KeyboardButton
{
[DefaultValue(Key.NoName)]
public Key EmulatedKey { get; set; }
}
// KeyboardPanel.cs
public class KeyboardButtonCollection : Collection<KeyboardButton> { }
public static class KeyboardPanel
{
internal const string ButtonsPropertyName = "Buttons";
static KeyboardPanel()
{
ButtonsProperty = DependencyProperty.RegisterAttached
(
ButtonsPropertyName,
typeof(KeyboardButtonCollection),
typeof(KeyboardPanel),
new UIPropertyMetadata(null, OnButtonsChanged)
);
}
public static KeyboardButtonCollection GetButtons(DependencyObject dependencyObject)
{
return (KeyboardButtonCollection)dependencyObject.GetValue(ButtonsProperty);
}
public static void SetButtons(DependencyObject dependencyObject, KeyboardButtonCollection value)
{
dependencyObject.SetValue(ButtonsProperty, value);
}
public static bool IsKeyboardPanel(DependencyObject dependencyObject)
{
return GetButtons(dependencyObject).Count != 0;
}
public static readonly DependencyProperty ButtonsProperty;
private static void OnButtonsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
bool isSupportedType = true;
if (dependencyObject is Panel)
{
var panel = (Panel)dependencyObject;
foreach (var button in (KeyboardButtonCollection)e.NewValue)
panel.Children.Add(button);
}
else
isSupportedType = false;
if (!isSupportedType)
throw new NotSupportedException(string.Format("Type {0} is not supported as KeyboardPanel.", dependencyObject.GetType()));
}
}
<!-- MainWindow.xaml -->
<Grid>
<controls:KeyboardPanel.Buttons>
<controls:KeyboardButtonCollection>
<controls:KeyboardButton Content="Enter" EmulatedKey="Enter"/>
<controls:KeyboardButton Grid.Row="1" Content="Some Key"/>
<controls:KeyboardButton Grid.Row="2" Content="Another Key"/>
</controls:KeyboardButtonCollection>
</controls:KeyboardPanel.Buttons>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="3" Content="Test" Loaded="Button_Loaded"/>
</Grid>
// MainWindow.xaml.cs
public partial class MainWindow : Window
{
private void Button_Loaded(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
if (KeyboardPanel.IsKeyboardPanel(button.Parent))
{
var enterButton = KeyboardPanel.GetButtons(button.Parent)
.FirstOrDefault(b => b.EmulatedKey == Key.Enter);
if (enterButton != null)
MessageBox.Show("KeyboardPanel contains an EnterButton");
else
MessageBox.Show("KeyboardPanel doesn't contain an EnterButton");
}
}
}
我一般不會在.NET編程,但 - 不時 - 我「被迫」用它創建一些工具。然而,你們中的一些人可能知道我如何消除此代碼的弱點:它不支持VisualStudio或Expression Blend Designer。因此,這些控件不能在設計時修改或者看到。
我剛剛發現,當沒有其他元素添加到該面板時,設計者確實會顯示附加的控件。似乎是一個設計師的錯誤。 – 0xbadf00d 2011-05-28 14:32:20