C#WPF绑定直到MouseOut才更新

时间:2013-11-19 13:09:19

标签: c# wpf visual-studio inotifypropertychanged

我有一个带有可点击标签的板(Grass和Unit),当我点击Grass标签时,它应该将Unit Label移动到Grass的x和y位置。它有效,但有点不对劲。当我点击标签时,在将光标移出已点击的标签之前没有任何反应,然后执行想要的行为。

XAML

<local:Grass Grid.Row="9" Grid.Column="16"   />
<local:Unit Grid.Row="{Binding Path=xPos, UpdateSourceTrigger=PropertyChanged}" Grid.Column="{Binding Path=yPos, UpdateSourceTrigger=PropertyChanged}" >
       <local:Unit.Background>
             <ImageBrush ImageSource="Images/tjej.png"/>
       </local:Unit.Background>
</local:Unit>

ObjectInspector

 public class ObjectInspector : INotifyPropertyChanged
{
    private int _xPos = 1, _yPos = 2;



    public int xPos
    {
        get { return _xPos; }
        set
        {
            _xPos = value;
            NotifyPropertyChanged("xPos");
        }
    }

    public int yPos
    {
        get { return _yPos; }
        set {
            _yPos = value;
            NotifyPropertyChanged("yPos");
        }
    }

    private string _type = "none";

    public string type
    {
        get { return _type; }
        set { 
            _type = value;
            NotifyPropertyChanged("type");
        }

    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            System.Diagnostics.Debug.WriteLine("property changed");

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

   public class Grass : Button
{

    protected override void OnClick()
    {
        base.OnClick();
        int x = (int)this.GetValue(Grid.RowProperty);
        int y = (int)this.GetValue(Grid.ColumnProperty);
        string type = this.GetType().Name;
        MainWindow.objectInspector.xPos = x;
        MainWindow.objectInspector.yPos = y;
        MainWindow.objectInspector.type = type;
    }
}

主窗口

  public partial class MainWindow : Window
{
    public static ObjectInspector objectInspector= new ObjectInspector();
    public MainWindow()
    {
        InitializeComponent();                       
        this.DataContext = objectInspector;


    }
}

有什么想法吗?

编辑 添加了MainWindow和Grass

2 个答案:

答案 0 :(得分:1)

修改

尝试注册按钮的公共事件处理程序Click

<local:Grass Grid.Row="9" Grid.Column="16"  Click="ClickEventHandler" />
...

在事件处理程序方法中从发件人那里获取grass元素。


无论如何,我认为更好的方法是使用MVVM模式。您可以设置GrassViewModelUnitViewModel。然后为每个创建一个DataTemplate。例如:

<DataTemplate DataType="{x:Type ViewModel:UnitViewModel}">
    ...Visual Elements Here...
</DataTemplate>

要在网格中显示元素,您可以使用ListBox并将Grid作为项目面板,有些像这样:

<ListBox ItemsSource={Binding AllItemsCollection}>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                ...rows and columns definitions here...
            </Grid>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <!--HERE THE ITEMS STYLE, HERE YOU SET THE COLUMN, ROW BINDINGS-->
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Grid.Row" Value="{Binding yPos}"/>
            <Setter Property="Grid.Column" Value="{Binding xPos}"/>
            <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
            <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

然后,您只需要在视图模型中使用所需的所有元素创建AllItemsCollection。您可以使用行为处理click事件,或者为草创建UserControl(并控制内部的click事件):

<DataTemplate DataType="{x:Type ViewModel:UnitViewModel}">
    <GrassUserControl ...Inside the grass user control you can handler the click event.../>
</DataTemplate>

希望有帮助...

答案 1 :(得分:1)

如果您的后续MVVM可以将属性附加到标签,如下所示。您可以将此行为附加到源自UIElement

的任何控件

为MouseClick创建附加属性

public class MouseClick
{
    public static readonly DependencyProperty MouseLeftClickProperty = 
        DependencyProperty.RegisterAttached("MouseLeftClick", typeof(ICommand), typeof(MouseClick),
        new FrameworkPropertyMetadata(CallBack));

    public static void SetMouseLeftClick(DependencyObject sender, ICommand value)
    {
        sender.SetValue(MouseLeftClickProperty, value);
    }

    public static ICommand GetMouseLeftClick(DependencyObject sender)
    {
        return sender.GetValue(MouseLeftClickProperty) as ICommand;
    }

    public static readonly DependencyProperty MouseEventParameterProperty =
        DependencyProperty.RegisterAttached(
            "MouseEventParameter",
            typeof(object),
            typeof(MouseClick),
            new FrameworkPropertyMetadata((object)null, null));


    public static object GetMouseEventParameter(DependencyObject d)
    {
        return d.GetValue(MouseEventParameterProperty);
    }


    public static void SetMouseEventParameter(DependencyObject d, object value)
    {
        d.SetValue(MouseEventParameterProperty, value);
    }

    private static void CallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if (sender != null)
        {
            UIElement element = sender as UIElement;
            if (element != null)
            {
                if (e.OldValue != null)
                {
                    element.RemoveHandler(UIElement.MouseDownEvent, new MouseButtonEventHandler(Handler));
                }
                if (e.NewValue != null)
                {
                    element.AddHandler(UIElement.MouseDownEvent, new MouseButtonEventHandler(Handler), true);
                }
            }
        }
    }
    private static void Handler(object sender, EventArgs e)
    {
        UIElement element = sender as UIElement;
        if (sender != null)
        {
            ICommand cmd = element.GetValue(MouseLeftClickProperty) as ICommand;
            if (cmd != null)
            {
                RoutedCommand routedCmd =cmd as RoutedCommand;
                object paramenter = element.GetValue(MouseEventParameterProperty);
                if (paramenter == null)
                {
                    paramenter = element;
                }
                if (routedCmd != null)
                {
                    if (routedCmd.CanExecute(paramenter, element))
                    {
                        routedCmd.Execute(paramenter, element);
                    }
                }
                else
                {
                    if (cmd.CanExecute(paramenter))
                    {
                        cmd.Execute(paramenter);
                    }
                }
            }
        }
    }
}

在你的Xaml中,你的viewModel的命令如下所示

 <Label Height="30" Width="200" Margin="10" Content="Click" local:MouseClick.MouseLeftClick="{Binding Click}" />