【问题标题】:How to properly set the DataContext of DataTemplate Controls如何正确设置 DataTemplate 控件的 DataContext
【发布时间】:2015-09-22 13:48:22
【问题描述】:

这是这个问题的后续:Items added to ItemsControl not using ItemTemplate

我有 2 个类应该处理对象的移动和调整大小(MoveThumbResizeThumb)。模板被应用于ItemsControl 中的对象,并且正在触发应该转换对象的函数,但我无法让它工作。

ItemsControl 绑定到“DashboardItems”的ObservableCollection,目前只是返回Canvas.SetTop/Left 的X 和Y 的简单对象。我可能会在未来添加它们,但我想先让基础知识发挥作用

MoveThumb_DragDelta 的比较中,'item' 始终为空。 ResizeThumb 有同样的问题。 发件人是MoveThumbsender.DataContextContentPresenter

我的问题是:我应该如何正确设置模板和/或类的数据上下文,以便MoveThumb_DragDelta 可以获取触发它的控件?

编辑: 将 Control item = this.DataContext as Control; 更改为 UIElement item = this.DataContext as UIElement; 使移动正常,但调整大小不起作用,因为 UIElement 不包含 ActualHeight/Width 或 MinHeight/Width。

MoveThumb:

public class MoveThumb : Thumb
{
    public MoveThumb()
    {
        DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
    }

    private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
    {
        Control item = this.DataContext as Control;
        if (item != null)
        {
            double left = Canvas.GetLeft(item);
            double top = Canvas.GetTop(item);

            Canvas.SetLeft(item, left + e.HorizontalChange);
            Canvas.SetTop(item, top + e.VerticalChange);
        }
    }
}

MainWindow.xaml:

<Window.Resources>
    <ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type local:MoveThumb}">
        <Rectangle Fill="Transparent"/>
    </ControlTemplate>
    <ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="Control">
        <Grid>
            <local:ResizeThumb Height="2" Cursor="SizeNS" Margin="0 -4 0 0" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
            <local:ResizeThumb Width="2" Cursor="SizeWE" Margin="-4 0 0 0" VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
            <local:ResizeThumb Width="2" Cursor="SizeWE" Margin="0 0 -4 0" VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
            <local:ResizeThumb Height="2" Cursor="SizeNS" Margin="0 0 0 -4" VerticalAlignment="Bottom"  HorizontalAlignment="Stretch"/>
            <local:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="-6 -6 0 0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
            <local:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="0 -6 -6 0" VerticalAlignment="Top" HorizontalAlignment="Right"/>
            <local:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="-6 0 0 -6" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
            <local:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="0 0 -6 -6" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
        </Grid>
    </ControlTemplate>
    <DataTemplate DataType="{x:Type local:TableControl}">
        <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
            <local:MoveThumb Template="{StaticResource MoveThumbTemplate}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Cursor="SizeAll"/>
            <Control Template="{StaticResource ResizeDecoratorTemplate}"/>
            <Button Content="x" VerticalAlignment="Top" HorizontalAlignment="Right" Width="10" Height="10" Click="Button_Click"/>
            <Ellipse Fill="Red" IsHitTestVisible="False" Height="100" Width="100"/>
        </Grid>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:GraphControl}">
        <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
            <local:MoveThumb Template="{StaticResource MoveThumbTemplate}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Cursor="SizeAll"/>
            <Control Template="{StaticResource ResizeDecoratorTemplate}"/>
            <Button Content="x" VerticalAlignment="Top" HorizontalAlignment="Right" Width="10" Height="10" Click="Button_Click"/>
            <Ellipse Fill="Green" IsHitTestVisible="False" Height="100" Width="100"/>
        </Grid>
    </DataTemplate>
</Window.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <ribbon:Ribbon Margin="0,-22,0,0" Grid.Row="0">
        <ribbon:RibbonTab Header="Dashboard">
            <ribbon:RibbonGroup Header="Customise">
                <ribbon:RibbonMenuButton Label="New"  FontSize="20" Height="60" Width="60">
                    <ribbon:RibbonMenuItem Header="Graph" Click="NewGraph"/>
                    <ribbon:RibbonMenuItem Header="Table" Click="NewTable"/>
                </ribbon:RibbonMenuButton>
            </ribbon:RibbonGroup>
        </ribbon:RibbonTab>
    </ribbon:Ribbon>

    <ItemsControl Name="dashboardControls" ItemsSource="{Binding Path=CanvasContents}" Grid.Row="1">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Top" Value="{Binding Path=Y}"/>
                <Setter Property="Canvas.Left" Value="{Binding Path=X}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
</Grid>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    public static Dashboard dashboard;

    public MainWindow()
    {
        dashboard = new Dashboard();

        InitializeComponent();

        this.DataContext = dashboard;

    }

    private void NewGraph(object sender, RoutedEventArgs e)
    {
        dashboard.CanvasContents.Add(new GraphControl());
    }

    private void NewTable(object sender, RoutedEventArgs e)
    {
        dashboard.CanvasContents.Add(new TableControl());
    }
}

Dashboard.cs:

public class Dashboard: INotifyPropertyChanged
{
    ObservableCollection<DashboardItem> _canvasContents;

    public Dashboard()
    {
        _canvasContents = new ObservableCollection<DashboardItem>();
    }

    public ObservableCollection<DashboardItem> CanvasContents
    {
        get { return _canvasContents; }
    }
}

DashboardItem.cs:

public abstract class DashboardItem
{
    public int X
    {
        get { return 100; }
    }

    public int Y
    {
        get { return 100; }
    }
}

【问题讨论】:

    标签: c# wpf xaml datacontext


    【解决方案1】:

    我还没有尝试过,但http://www.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part 似乎有你的答案。

    编辑: 我从 cmets 看到问题在于从 Canvas 移动到 ItemsControl。在这种情况下,Canvas.TopCanvas.Left 似乎存在问题,以及设置一些样式属性的解决方案:Dragable objects in WPF in an ItemsControl?

    【讨论】:

    • 我可能应该在我的答案中将其链接起来,但这就是我的模板以及 MoveThumb 和 ResizeThumb 的基础。它一直在工作,直到我从使用画布切换到 ItemsControl 然后我不得不做很多工作才能让模板正常工作
    • 啊,对不起。我应该意识到的。只是想知道,如果您的 xaml 没有画布,那么您的 movethumb 中的画布引用会做什么。找到stackoverflow.com/questions/3367922/…,提示canvas.Top等有问题,或许有解决办法。
    • 我已将 ItemsControl 中的 ItemsPanel 设置为使用 Canvas 模板,或者至少我认为它是这样做的。我查看了该链接,只需将 Control item = this.DataContext as Control; 更改为 UIElement item = this.DataContext as UIElement; 即可使运动正常运行,但尚未调整大小。
    • 虽然有进步 :) 对不起,我不是专家 - 我只记得看到过一些类似的东西。祝你好运。
    猜你喜欢
    • 2016-02-06
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多