C# 从数组进行绑定更新

C# 从数组进行绑定更新,c#,.net,wpf,arrays,data-binding,C#,.net,Wpf,Arrays,Data Binding,我不确定数组是否真的是这里的问题,但我有一个矩形,我想在引发MouseUp事件时将其从窗口的一侧移动到另一侧。我将这个矩形绑定到一个数组元素,MouseUp事件处理程序方法更改该数组的值。我知道handler方法可以很好地拉起消息框,只是不能切换矩形的位置 注意:数组是必需的,这只是测试这些概念的代码,而不是我的实际项目 此外,解决此问题的最简单方法也将不胜感激 C#代码: XAML代码: <Window x:Class="WPFTestingApplication.MainWindow"

我不确定数组是否真的是这里的问题,但我有一个矩形,我想在引发MouseUp事件时将其从窗口的一侧移动到另一侧。我将这个矩形绑定到一个数组元素,MouseUp事件处理程序方法更改该数组的值。我知道handler方法可以很好地拉起消息框,只是不能切换矩形的位置

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

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

C#代码:

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>

好的,现在我们必须把Windows窗体的心态放在一边(呵呵)。在WPF中,您需要考虑功能和外观之间的分离。也就是说,您允许您的代码(c#)确定功能方面,然后在xaml中进行一些模板化以使其具有外观

您真正想要的功能是拇指的功能。thumb中已经内置了拖动功能,因此您只需要创建一个模板来显示它的外观

首先看看这个:

我将通过创建您自己的类来实现这一点,该类由thumb派生,如下所示:

// 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);
    }
}
<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>
然后创建一个模板,如下所示:

// 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);
    }
}
<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>

现在把它放到画布上,你就完成了

<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>

阵列就是问题所在。你应该仔细阅读,没有它,你绑定到的任何东西都不会更新

如果可以,请将数组更改为
ObservableCollection
,它实现
INotifyPropertyChanged
以更改其元素。您可以将其作为数组进行索引

在静态类中存储属性集合时,您可能也会遇到问题。静态类和属性没有属性更改通知。如果GridProperties可以成为window类上的一个属性,那就更容易了。然后,将窗口的DataContext设置为自身

类似这样的东西适用于您的示例。但是,无法判断实际项目中是否有更复杂的内容

C#:

公共部分类主窗口:窗口
{
公共ObservableCollection GridProperties{get;private set;}
公共主窗口()
{
初始化组件();
GridProperties=新的ObservableCollection();
GridProperties.Add(0);
DataContext=this;
}
私有void Rect_MouseUp_1(对象发送器,MouseButtonEventArgs e)
{
GridProperties[0]=1;
}
}
xaml:



对于我想做的事情来说,这似乎太复杂了,我只是在数组更改时更新数据绑定时遇到了一个问题。好吧,让我们看看是否无法找出您缺少了什么。那么,您使用阵列的目的是什么?用于包含可拖动框?数组用于8个可单击框的{row,column}坐标,这将是一个滑动益智游戏,当我单击其中一个时,如果可以,它必须移动到一个空白处。哦,我明白了,你可以试着看看这个:
<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>