我为外部资源字典中的DataTemplate
项定义了以下ListBox
:
<DataTemplate x:Key="MyListBoxItemTemplate" DataType="{x:Type entities:Track}">
<StackPanel>
<TextBlock Text="Here's the slider:" />
<Slider Name="MySlider" Height="23" Minimum="0" />
</StackPanel>
</DataTemplate>
我需要为Slider的ValueChanged
事件提供事件处理程序方法。我不知道我应该在哪里编写代码,因为为模板中的控件指定事件处理程序是不切实际的。
我一直在谷歌搜索解决方案,发现我应该在OnApplyTemplate()
方法的覆盖中添加事件处理程序。我的猜测是它应该看起来像这样或类似的东西:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Is the following initialization even going to work!?!?
Slider MySlider = this.FindName("MySlider") as Slider;
SeekSlider.ValueChanged +=
new RoutedPropertyChangedEventHandler<double>(SeekSlider_ValueChanged);
}
但是我应该在哪里写这个方法? OnApplyTemplate覆盖仅适用于ControlTemplates还是包含在我的场景中?我应该提供ControlTemplate而不是DataTemplate吗?我提供的方法正文是否正确?
请帮忙。谢谢。
答案 0 :(得分:6)
如果您正在使用OnApplyTemplate
控件,则使用ControlTemplate
方法将有效。例如,如果您已经将TextBox
子类化,则可以像
public class MyTextBox : TextBox
{
public override void OnApplyTemplate()
{
MySlider MySlider = GetTemplateChild("MySlider") as MySlider;
if (MySlider != null)
{
MySlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(MySlider_ValueChanged);
}
base.OnApplyTemplate();
}
void MySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
//...
}
}
我不认为这种方法适用于您的情况。您可以使用ListBoxItem
的Loaded事件,并在事件处理程序中的可视树中找到Slider
<ListBox ...>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="Loaded" Handler="ListBoxItem_Loaded"/>
</Style>
</ListBox.ItemContainerStyle>
<!--...-->
</ListBox>
代码
private void ListBoxItem_Loaded(object sender, RoutedEventArgs e)
{
ListBoxItem listBoxItem = sender as ListBoxItem;
Slider MySlider = GetVisualChild<Slider>(listBoxItem);
MySlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(MySlider_ValueChanged);
}
void MySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
}
<强> GetVisualChild 强>
private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
答案 1 :(得分:3)
鲜为人知的事实是ResourceDictionaries也可以拥有CodeBehind ..
作为一般的经验法则,我不认为将DataTemplates放在ResourceDictionaries中是一个好主意开始(你的问题是其中一个原因的例子),这就是你如何解决它:
XAML:
<ResourceDictionary
x:Class="WpfApplication24.Dictionary1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate x:Key="MyDataTemplate">
<StackPanel>
<TextBlock Text="Hello" />
<Slider ValueChanged="ValueChanged"/>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
和代码背后:
namespace WpfApplication24
{
public partial class Dictionary1 : ResourceDictionary
{
public void ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Debug.Write("Hello");
}
}
}
无论如何,正如Meleak在我上面所说的那样 - OnApplyTemplate仅与控制模板有关,而与数据模板无关。
答案 2 :(得分:0)
答案 3 :(得分:0)
您可以在设置模板的样式中使用EventSetter
:
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="MouseWheel" Handler="GroupListBox_MouseWheel" />
<Setter Property="Template" ... />
</Style>
答案 4 :(得分:0)
方法1 :
使用您自己的控件继承自Slider
:
public class SpecialSlider : Slider
{
public SpecialSlider()
{
ValueChanged += OnValueChanged;
}
private void OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
// ...
}
}
方法2 :使用System.Windows.Interactivity.dll程序集中的行为(可通过NuGet获得):
public class SpecialSliderBehavior : Behavior<Slider>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.ValueChanged += OnValueChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.ValueChanged -= OnValueChanged;
}
private void OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
// ...
}
}
这是如何附加它:
...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...
<DataTemplate x:Key="MyListBoxItemTemplate" DataType="{x:Type entities:Track}">
<Slider Name="MySlider">
<i:Interaction.Behaviors>
<SpecialSliderBehavior />
</i:Interaction.Behaviors>
</Slider>
</DataTemplate>