gpt4 book ai didi

wpf - 如何重用 DataTemplate 中的控件实例?

转载 作者:行者123 更新时间:2023-12-01 02:50:16 27 4
gpt4 key购买 nike

我几乎没有带有视频控件的布局(不同的 DataTemplates)。这个视频控件的创建时间很长。我想在不同的 DataTemplates 中重用这个视频控件的实例。

牵强的例子:

代码隐藏和 ViewModel:

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();

Layout1 = (DataTemplate)this.FindResource("_layout1");
Layout2 = (DataTemplate)this.FindResource("_layout2");

DataContext = new ViewModel {Content1 = "Content1", Content2 = "Content2"};
}

private void Button_Click(object sender, RoutedEventArgs e)
{
_view.ContentTemplate = _view.ContentTemplate == Layout1 ? Layout2 : Layout1;
}

DataTemplate Layout1;
DataTemplate Layout2;
}

public class ViewModel
{
public string Content1 { get; set; }
public string Content2 { get; set; }
}

XAML
<Window Name="_mainForm" x:Class="WpfVideo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:model="clr-namespace:WpfVideo"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="_layout1" DataType="{x:Type model:ViewModel}">
<StackPanel>
<Button Content="{Binding Content1}"/>
<Button Content="{Binding Content2}"/>
</StackPanel>
</DataTemplate>

<DataTemplate x:Key="_layout2" DataType="{x:Type model:ViewModel}">
<StackPanel Orientation="Horizontal">
<Button Content="{Binding Content1}"/>
<Button Content="{Binding Content2}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>

<StackPanel>
<Button Click="Button_Click">Change</Button>
<ContentPresenter Name="_view" Content="{Binding}" ContentTemplate="{StaticResource _layout1}"/>
</StackPanel>

如何重用按钮并防止在每次模板更改时创建新按钮?

已编辑:在 Button_click 上使用数据模板 _layout1 和 _layout2 之间的切换。只有一个模板处于事件状态。我不想在两个地方绘制一个控件实例。我想防止在其他模板激活时(之前停用)在其他模板中创建控件。
或者也许我可以使用另一种方法,没有数据模板?风格、资源、触发器?

最佳答案

控制池

ControlsPoolControl<T> 
IControlsPool<T>
  • T——可重用控件的类型。
  • IControlsPool - 用于存储
    可重用的按键控制实例
    对象( View 模型的某些属性)
  • ControlsPoolControl - 容器,
    从中恢复内部控制
    IControlsPool 通过绑定(bind)键。

  • 执行
    控制池控制
    public class ControlsPoolControl<T> : UserControl where T : UIElement
    {
    private readonly Panel _mainPanel;
    private T _innerControl;

    public ControlsPoolControl()
    {
    _mainPanel = new Grid();
    Content = _mainPanel;
    }

    #region Properties

    #region DependencyProperty

    public static readonly DependencyProperty KeyObjectProperty = DependencyProperty.Register("KeyObject", typeof(object), typeof(ControlsPoolControl<T>), new PropertyMetadata(null, KeyObjectChanged));
    public static readonly DependencyProperty PoolProperty = DependencyProperty.Register("Pool", typeof(IControlsPool<T>), typeof(ControlsPoolControl<T>), new PropertyMetadata(null, PoolChanged));

    #endregion

    public object KeyObject
    {
    get { return GetValue(KeyObjectProperty); }
    set { SetValue(KeyObjectProperty, value); }
    }

    public IControlsPool<T> Pool
    {
    get { return (IControlsPool<T>)GetValue(PoolProperty); }
    set { SetValue(PoolProperty, value); }
    }

    protected T InnerControl
    {
    get { return _innerControl; }
    set
    {
    if (_innerControl == value)
    return;

    _innerControl = value;
    OnControlChanged();
    }
    }

    #endregion

    #region Private API

    void Clear()
    {
    _mainPanel.Children.Clear();
    }

    void OnKeyObjectChanged()
    {
    UpdateControl();
    }

    void OnControlChanged()
    {
    VerifyAccess();
    Clear();

    var ctrl = InnerControl;
    if (ctrl != null)
    _mainPanel.Children.Add(ctrl);
    }

    private void UpdateControl()
    {
    if (KeyObject == null || Pool == null)
    InnerControl = null;
    else
    InnerControl = Pool.Get(KeyObject);
    }

    private static void KeyObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    ((ControlsPoolControl<T>)d).OnKeyObjectChanged();
    }

    private static void PoolChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    ((ControlsPoolControl<T>)d).UpdateControl();
    }

    #endregion
    }
    控制池
    public interface IControlsPool<T> where T : UIElement
    {
    void Add(object key, T control);
    T Get(object key);
    }

    public class ControlsPool<T> : IControlsPool<T> where T : UIElement
    {
    readonly IDictionary<object, T> _controls = new Dictionary<object, T>();

    public void Add(object key, T control)
    {
    if (key == null) throw new ArgumentNullException("key");

    if (_controls.ContainsKey(key)) return;
    _controls.Add(key, control);
    }

    public T Get(object key)
    {
    if (key == null) throw new ArgumentNullException("key");

    T control = null;
    if (!_controls.TryGetValue(key, out control))
    {
    control = CreateInstance(key);
    _controls.Add(key, control);
    }

    return control;
    }

    protected virtual T CreateInstance(object key)
    {
    return Activator.CreateInstance<T>();
    }
    }
    用法
    代码隐藏
    public partial class MainWindow : Window
    {
    public MainWindow()
    {
    InitializeComponent();

    ContentControlType = typeof(MyButton);

    Layout1 = (DataTemplate)FindResource("_layout1");
    Layout2 = (DataTemplate)FindResource("_layout2");

    DataContext = new ViewModel { Content1 = "Content1", Content2 = "Content2" };
    }

    public Type ContentControlType { get; set; }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
    _view.ContentTemplate = _view.ContentTemplate == Layout1 ? Layout2 : Layout1;
    }

    DataTemplate Layout1;
    DataTemplate Layout2;
    }

    public class ViewModel
    {
    public string Content1 { get; set; }
    public string Content2 { get; set; }
    }

    public class ButtonsPool : ControlsPool<MyButton> { }

    public class ButtonPoolControl : ControlsPoolControl<MyButton>
    {
    }

    public class MyButton : Button
    {
    static int _counter = 0;

    public MyButton()
    {
    _counter++;
    }
    }
    XAML
    要初始化可重用控件,您应该使用样式。
    <Window Name="_mainForm" x:Class="WpfVideo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:model="clr-namespace:WpfVideo"
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>

    <model:ButtonsPool x:Key="_buttonsPool"/>

    <DataTemplate x:Key="_layout1" DataType="{x:Type model:ViewModel}">
    <StackPanel>
    <model:ButtonPoolControl KeyObject="{Binding Content1}" Pool="{StaticResource _buttonsPool}">
    <model:ButtonPoolControl.Resources>
    <Style TargetType="model:MyButton">
    <Setter Property="Content" Value="{Binding Content1}"/>
    </Style>
    </model:ButtonPoolControl.Resources>
    </model:ButtonPoolControl>
    <model:ButtonPoolControl KeyObject="{Binding Content2}" Pool="{StaticResource _buttonsPool}">
    <model:ButtonPoolControl.Resources>
    <Style TargetType="model:MyButton">
    <Setter Property="Content" Value="{Binding Content2}"/>
    </Style>
    </model:ButtonPoolControl.Resources>
    </model:ButtonPoolControl>
    </StackPanel>
    </DataTemplate>

    <DataTemplate x:Key="_layout2" DataType="{x:Type model:ViewModel}">
    <StackPanel Orientation="Horizontal">
    <model:ButtonPoolControl Pool="{StaticResource _buttonsPool}" KeyObject="{Binding Content1}">
    <model:ButtonPoolControl.Resources>
    <Style TargetType="model:MyButton">
    <Setter Property="Content" Value="{Binding Content1}"/>
    </Style>
    </model:ButtonPoolControl.Resources>
    </model:ButtonPoolControl>
    <model:ButtonPoolControl Pool="{StaticResource _buttonsPool}" KeyObject="{Binding Content2}">
    <model:ButtonPoolControl.Resources>
    <Style TargetType="model:MyButton">
    <Setter Property="Content" Value="{Binding Content2}"/>
    </Style>
    </model:ButtonPoolControl.Resources>
    </model:ButtonPoolControl>
    </StackPanel>
    </DataTemplate>
    </Window.Resources>

    <StackPanel>
    <Button Click="Button_Click">Change</Button>
    <ContentPresenter Name="_view" Content="{Binding}" ContentTemplate="{StaticResource _layout1}"/>
    </StackPanel>
    </Window>

    关于wpf - 如何重用 DataTemplate 中的控件实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5484703/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com