Programmatically access a control from a DataTemplate

匆匆过客 提交于 2019-12-11 04:28:32

问题


What's a good way to get at the controls in a DataTemplate? I've used the technique of handing the Loaded event on the control of interest as well as using VisualTreeHelper to walk the visual tree and neither of those is very elegant. What's a good way to access DataTemplate controls?

In one example, I need to add a binding whos ConverterParameter isn't know at design time, and since binding to ConverterParameters isn't supported I need to create the binding in code. Ideally I'd like to be able to do this somewhere other than the Loaded event hander for the control in the datatemplate.

In fact, in this scenario handling events doesn't work at all and causes the an OutOfMemoryException. Here's my attempt:

generic.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SilverlightTest">


    <Style TargetType="local:TemplatedControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:TemplatedControl">
                    <ListBox ItemsSource="{TemplateBinding ListBoxItemsSource}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock x:Name="SomeTextBlock"
                                    Loaded="SomeTextBlock_Loaded"/>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

templatedcontrol.cs:

public class TemplatedControl : Control
    {
        public object ListBoxItemsSource
        {
            get { return (object)GetValue(ListBoxItemsSourceProperty); }
            set { SetValue(ListBoxItemsSourceProperty, value); }
        }

        public static readonly DependencyProperty ListBoxItemsSourceProperty =
            DependencyProperty.Register
            ("ListBoxItemsSource", typeof(object),
             typeof(TemplatedControl), new PropertyMetadata(null));

        public TemplatedControl()
        {
            this.DefaultStyleKey = typeof(TemplatedControl);
        }

        public void SomeTextBlock_Loaded(object sender, RoutedEventArgs ea)
        {
        }
    }

回答1:


You could have another control in your DataTemplate to handle that, but that's kind of messy also with the caveat of "unless you really believe the logic justifies it".

You might want to rethink your approach. In my opinion (and it's just an opinion!), one should only be binding in code in more exotic situations.

Maybe instead of using a IValueConverter, bind to a property on the a ViewModel (assuming your ItemsSource is a collection of ViewModels), and let your VM convert your values accordingly. Let your default style for this control be generic and ugly and maybe use specific styles for cases when you need to bind to specific properties.



来源:https://stackoverflow.com/questions/1380925/programmatically-access-a-control-from-a-datatemplate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!