我一直在尝试通过大量谷歌搜索和 SO 来解决这个问题,但不幸的是我无法解决这个问题。我读得越多,就越困惑。
我想构建一个自动完成文本框作为自定义控件。
我的自定义控件:
<UserControl x:Class="ApplicationStyling.Controls.AutoCompleteTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ApplicationStyling.Controls"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
Name="AutoCompleteBox">
<Grid>
<TextBox Grid.Row="3"
Style="{DynamicResource InputBox}"
x:Name="SearchBox"
Text="{Binding Text}"
TextChanged="{Binding ElementName=AutoCompleteBox, Path=TextChanged}"/>
<ListBox x:Name="SuggestionList"
Visibility="Collapsed"
ItemsSource="{Binding ElementName=AutoCompleteTextBox, Path=SuggestionsSource}"
SelectionChanged="{Binding ElementName=AutoCompleteBox, Path=SelectionChanged}">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Label}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
我的代码背后:
using System.Collections;
using System.Windows;
using System.Windows.Controls;
namespace ApplicationStyling.Controls
{
/// <summary>
/// Interaction logic for AutoCompleteTextBox.xaml
/// </summary>
public partial class AutoCompleteTextBox : UserControl
{
public static readonly DependencyProperty SuggestionsSourceProperty;
public static readonly DependencyProperty TextProperty;
// Events
public static readonly RoutedEvent TextChangedProperty;
public static readonly RoutedEvent SelectionChangedProperty;
static AutoCompleteTextBox()
{
// Attributes
AutoCompleteTextBox.SuggestionsSourceProperty = DependencyProperty.Register("SuggestionsSource", typeof(IEnumerable), typeof(AutoCompleteTextBox));
AutoCompleteTextBox.TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteTextBox));
// Events
AutoCompleteTextBox.TextChangedProperty = EventManager.RegisterRoutedEvent("TextChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AutoCompleteTextBox));
AutoCompleteTextBox.SelectionChangedProperty = EventManager.RegisterRoutedEvent("SelectionChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AutoCompleteTextBox));
}
#region Events
public event RoutedEventHandler TextChanged
{
add { AddHandler(TextChangedProperty, value); }
remove { RemoveHandler(TextChangedProperty, value); }
}
// This method raises the Tap event
void RaiseTextChangedEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(AutoCompleteTextBox.TextChangedProperty);
RaiseEvent(newEventArgs);
}
public event RoutedEventHandler SelectionChanged
{
add { AddHandler(SelectionChangedProperty, value); }
remove { RemoveHandler(SelectionChangedProperty, value); }
}
// This method raises the Tap event
void RaiseSelectionChangedEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(AutoCompleteTextBox.SelectionChangedProperty);
RaiseEvent(newEventArgs);
}
#endregion
#region DProperties
/// <summary>
/// IEnumerable ItemsSource Property for the Suggenstion Box
/// </summary>
public IEnumerable SuggestionsSource
{
get
{
return (IEnumerable)GetValue(AutoCompleteTextBox.SuggestionsSourceProperty);
}
set
{
SetValue(AutoCompleteTextBox.SuggestionsSourceProperty, value);
}
}
/// <summary>
/// This is the Text attribute which routes to the Textbox
/// </summary>
public string Text
{
get
{
return (string)GetValue(AutoCompleteTextBox.TextProperty);
}
set
{
SetValue(AutoCompleteTextBox.TextProperty, value);
}
}
#endregion
public AutoCompleteTextBox()
{
InitializeComponent();
SearchBox.TextChanged += (sender, args) => RaiseTextChangedEvent();
SuggestionList.SelectionChanged += (sender, args) => RaiseSelectionChangedEvent();
}
}
}
最后,我使用它的方式:
<asc:AutoCompleteTextBox x:Name="ShareAutoCompleteBox"
Grid.Row="3"
SelectionChanged="ShareAutoCompleteBox_SelectionChanged"
TextChanged="ShareAutoCompleteBox_TextChanged"/>
其中 asc
是通过 app.xaml 加载的外包类库的命名空间。
无论如何,我在 XAML 中的 TextBox.TextChanged
属性以及运行代码时遇到的问题:
System.InvalidCastException: Unable to cast object of type 'System.Reflection.RuntimeEventInfo' to type 'System.Reflection.MethodInfo'.
那么这里到底发生了什么?我想将 AutoCompleteTextBox TextChanged
转发到自定义控件模板中的 TextBox
。与 SelectionChanged
到 Listbox
相同。
我从 https://msdn.microsoft.com/en-us/library/ms752288(v=vs.100).aspx 中获取了大部分代码(对于事件)和其他一些 SO 质疑自定义属性的代码。
不确定,问题是什么,我期待您的帮助。
最佳答案
发生异常是因为您试图将 TextChanged
字段的值绑定(bind)到需要方法引用的属性。它真的让 WPF 感到困惑。 :)
只需从 XAML 中的 TextBox
元素中删除 TextChanged
属性:
TextChanged="{Binding ElementName=AutoCompleteBox, Path=TextChanged}"
您已经在构造函数中订阅了该事件,这就足够了。如果您确实想在构造函数中使用 TextChanged
属性而不是 订阅,那么您可以这样做,但您需要提供一个实际的事件处理程序,例如代码隐藏中的一个方法。该方法将只调用 RaiseTextChangedEvent()
方法,就像您当前的事件处理程序所做的那样。只是它将是类中的命名方法,而不是构造函数中声明的匿名方法。
同样的事情适用于其他事件。
也就是说,您可能会重新考虑实现转发的事件。通常,您的控件的 Text
属性将绑定(bind)到某个模型对象的属性,当该绑定(bind)属性更改时,该对象本身可以做出适当的 react 。它不需要 UserControl
对象上的单独事件来告诉它它的值已更改。
关于c# - 将传统事件添加到自定义控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36254145/