【问题标题】:Accessing Canvas properties inside DataTemplate, WPF访问 DataTemplate、WPF 中的 Canvas 属性
【发布时间】:2014-06-02 16:43:21
【问题描述】:

我有一个用于文本的 DataTemplate,我使用 ItemControl 将文本放置在画布中。如何访问数据模板中的画布属性?如果很难我想访问 ItemControl 中的单个文本框属性。原因是我需要做一些文本控件对齐。我的 DataTemplate 和 ItemControl 代码都在下面

<DataTemplate
    DataType="{x:Type local:Text}">
    <TextBlock Text="{Binding Description}"
               FontSize= "{Binding Thickness}" 
               RenderTransformOrigin="0.5,0.5" 
               Foreground="#FFF63AFF" 
               FontWeight="Bold" >  
    <TextBlock.RenderTransform>
        <TransformGroup>
            <TranslateTransform X= "{Binding StartPoint.X}" Y= "{Binding StartPoint.Y}"  />                   
            <RotateTransform Angle= "{Binding Angle}"  />
        </TransformGroup>   
    </TextBlock.RenderTransform>  
    </TextBlock>
</DataTemplate>  


<ItemsControl ItemsSource="{Binding Path = TextList}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate> 
            <Canvas HorizontalAlignment="Center" VerticalAlignment="Center"
                Width="0" Height="0">  
                <Canvas.RenderTransform>
                <TransformGroup>                     
                    <ScaleTransform ScaleX="1" ScaleY="1"/>                                
                </TransformGroup>
                </Canvas.RenderTransform>
            </Canvas>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl> 

【问题讨论】:

    标签: wpf wpf-controls datatemplate


    【解决方案1】:

    如果您想自定义 ItemsControl 的子项的布局并且可用的面板不能满足您的需求,您可能必须构建自己的面板。下面是题目的介绍:http://www.codeproject.com/Articles/15705/FishEyePanel-FanPanel-Examples-of-custom-layout-pa

    难度取决于您的布局将是什么样子。在您的面板中,您可以访问布局逻辑的所有元素属性。例如,如果您想对齐面板右侧的所有多行文本框和左侧的所有单行文本框,这很容易做到。 :)

    如果您详细说明您想要实现的目标,我可以为您提供更好的指导。

    ---- 编辑 --- Canvas.Left 和其他的是 AttachedProperties。例如,您可以使用以下语法绑定模板内的分配值:

    MyProperty="{Binding Path=(Canvas.Left), RelativeSource={RelativeSource TemplatedParent}}"
    

    ---- 编辑 2 ---

    所以这里有一个示例,应该可以满足您的需求。在 ViewModel 中有一个包含点 (X & Y) 的集合。这些在带有画布面板的 ItemsControl 中呈现。棘手的部分是每个元素周围都有一个 ContentPresenter,因此无法将 Canvas 值绑定到 ItemTemplate 中的 Button。因此我添加了 ItemContainerStyle:

    MainWindow.Xaml

    <Window x:Class="WpfApplication7.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525" >
        <ItemsControl ItemsSource="{Binding Locations}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="Point">
                    <Button Content="{Binding}" Width="40" Height="20" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Setter Property="Canvas.Left"
                        Value="{Binding X}" />
                    <Setter Property="Canvas.Top"
                        Value="{Binding Y}" />
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
    </Window>
    

    MainWindow.Xaml.cs:

    public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new ViewModel();
            }
        }
    

    视图模型:

    public class ViewModel : INotifyPropertyChanged
        {
            public ViewModel()
            {
                Locations = new ObservableCollection<Point>
                {
                    new Point(10,10),
                    new Point(20,20),
                    new Point(30,30),
                    new Point(50,60),
                };
            }
    
            public ObservableCollection<Point> Locations { get; set; }
    
            #region INotifyPropertyChanged Support
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            [NotifyPropertyChangedInvocator]
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
            }
    
            #endregion
    
        }
    

    试试吧,我相信它应该可以满足您的需求。 :)

    【讨论】:

    • @@Gope 实际上我想将文本控件放置在画布内的某个位置(绝对位置)。这是这个问题stackoverflow.com/questions/23904132/…的延续。
    • 这取决于,您使用 Canvas.Left 和 Canvas.Top 有什么问题?如果您只需要为某些文本框分配一个位置,请使用 Canvas.Left 等附加属性。如果它变得更复杂,那么您将需要一个自定义面板或一个辅助类来迭代所有元素并将它们移动到正确的位置(这基本上是面板的作用)。
    • 以防万一这不清楚。您可以将 Canvas.Top 和其他属性绑定到任何数据,并使用转换器来计算最终位置。如果您需要画布大小才能使其工作并且转换器参数不可绑定,您可以从依赖对象派生转换器,提供依赖属性并将其在视图中绑定到画布大小。这应该有效。
    • 我编辑了我的答案。它向您展示了如何通过模板内的绑定来访问 AttachedProperty。
    • '构建了一个示例,展示了如何仅根据给定的点列表在画布内定位按钮。请参阅上面的答案(编辑 2):)
    猜你喜欢
    • 2019-03-02
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 2010-10-16
    • 2015-09-09
    • 2017-10-17
    相关资源
    最近更新 更多