0

我不确定数组是否真的是这里的问题,但我有一个矩形,当引发 MouseUp 事件时,我想将它从窗口的一侧移动到另一侧。我将此矩形绑定到一个数组元素,并且 MouseUp 事件处理程序方法更改了该数组的值。我知道处理程序方法可以正常工作,因为它可以很好地拉出一个消息框,只是不切换矩形的位置。

注意:数组是必须的,这只是测试这些概念的代码,不是我的实际项目。

解决此问题的最简单方法也将不胜感激。

C#代码:

namespace WPFTestingApplication
{
    public static class GridProperties
    {
        public static int[] gridColumn = { 0 };
    }

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

        private void Rect_MouseUp_1(object sender, MouseButtonEventArgs e)
        {
            GridProperties.gridColumn[0] = 1;
        }
    }
}

XAML 代码:

<Window x:Class="WPFTestingApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFTestingApplication"
        Title="MainWindow" Height="200" Width="400">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Rectangle Name="Rect" Grid.Column="{Binding [0], Source={x:Static local:GridProperties.gridColumn}, Mode=OneWay}" Fill="DarkGray" Margin="5" MouseUp="Rect_MouseUp_1"/>
    </Grid>
</Window>
4

2 回答 2

0

Okay, so here's where we have to put away the Windows Forms mentality (heh). In WPF you need to think about the separation between functionality and appearance. That is, you allow your code (c#) to determine the functionality aspect, and then do some templating in xaml to give it the appearance.

The functionality you actually want is that of a Thumb. A thumb already has the dragging functionality built into it, so you just need to create a template to give it it's appearance.

First take a look at this:

http://wpf.2000things.com/tag/dragging/

I would approach this by creating your own class that derives from thumb like this:

// Although the visual template we're applying is a circle,
// the FUNCTIONALITY is primarily that of a thumb. So that's what 
// we'll use. A thumb is essentially a 'draggable thing'.
class DragCircle : System.Windows.Controls.Primitives.Thumb
{      
    public DragCircle()
    {
        // Thumbs _track_ movement, but they don't actually move. We have to handle this ourselves.
        // We do this by setting the Canvas.Left/Canvas.Top attached properties. Of course, for this
        // to work our DragCircle has to be placed on a Canvas, otherwise there's no-one to read the property.
        // IMPORTANT! In order to read the Canvas position later, it needs to have a record in the WPF 
        // dependency property table. So for now we'll just set it to '0' as a default.
        Canvas.SetLeft (this, 0);
        Canvas.SetTop (this, 0);

        // The drag-delta event occurs when the Thumb is dragged. 'delta' represents "change" just like
        // we all learned in calculus.
        this.DragDelta += new System.Windows.Controls.Primitives.DragDeltaEventHandler(DragCircle_DragDelta);
    }

    void DragCircle_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
    {
        // Read the Canvas location from the WPF database.
        Double currentX = Canvas.GetLeft(this);
        Double currentY = Canvas.GetTop(this);

        // Now update the canvas attached properties using the drag-delta ('change in position').
        // Note that Canvas.SetLeft is just a helper function that maps to the attached property: 
        //  this.SetValue(Canvas.TopProperty, SOME_VALUE);
        Canvas.SetLeft(this, currentX + e.HorizontalChange);
        Canvas.SetTop(this, currentY + e.VerticalChange);
    }
}

Then just createa template like this:

<Window.Resources>
    <Style TargetType="lol:DragCircle">
        <Setter Property="Foreground" Value="LightGreen" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="lol:DragCircle">
                    <Ellipse Width="20" Height="20" Fill="{TemplateBinding Foreground}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Foreground" Value="Orange" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

Now drop it onto a canvas, and you're done.

<Canvas>
    <lol:DragCircle Canvas.Left="100" Canvas.Top="200" />
    <lol:DragCircle Canvas.Left="50" Canvas.Top="50" />
    <lol:DragCircle Canvas.Left="300" Canvas.Top="400" />
</Canvas>
于 2013-02-05T16:31:18.440 回答
0

The array is the problem. You should read up on INotifyPropertyChanged, nothing you bind to will be updated without it.

If you can, change your array to an ObservableCollection which implements INotifyPropertyChanged for changes to its elements. You can index it just like it's an array.

You may also have issues with storing the property collection in a static class. Static classes and properties don't have property changed notifications. If it's possible for the GridProperties to be a property on the window class that will be easier. Then, set the DataContext of the window to itself.

Something like this works for your example. Can't tell if you have something more complicated in your actual project though.

C#:

public partial class MainWindow : Window
{
    public ObservableCollection<int> GridProperties { get; private set; }

    public MainWindow()
    {
        InitializeComponent();
        GridProperties = new ObservableCollection<int>();
        GridProperties.Add(0);
        DataContext = this;
    }

    private void Rect_MouseUp_1(object sender, MouseButtonEventArgs e)
    {
        GridProperties[0] = 1;
    }
}

xaml:

<Grid>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Rectangle Name="Rect" Grid.Column="{Binding GridProperties[0]}" Fill="DarkGray" Margin="5" MouseUp="Rect_MouseUp_1"/>
</Grid>
于 2013-02-06T14:21:01.283 回答