简体   繁体   English

C#WPF绑定直到MouseOut才更新

[英]C# WPF Bindings not updating until MouseOut

I have a board with clickable labels (Grass and Unit), When I click a Grass label I it should move the Unit Label to the Grass's x and y position. 我有一个带有可单击标签(草和单位)的木板,当我单击草标签时,应将单位标签移到草的x和y位置。 It works, but kinda wrong. 它有效,但是有点不对。 When I click on a label, nothing happens until I move the cursor out of the clicked label, then the wanted behaviour executes. 当我单击标签时,什么都没有发生,直到我将光标移出所单击的标签,然后执行所需的行为。

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

Grass

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

MainWindow 主窗口

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


    }
}

Any ideas? 有任何想法吗?

Edit Added MainWindow and Grass 编辑添加的MainWindow和Grass

EDIT 编辑

Try to register to the common event handler Click of buttons: 尝试注册到公共事件处理程序, Click按钮:

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

And take the grass element from the sender, in the event handler method. 在事件处理程序方法中,从发件人处获取grass元素。


Anyway, I think a better way for doing this is usin MVVM patter. 无论如何,我认为使用MVVM模式是更好的方法。 You may set a GrassViewModel and UnitViewModel . 您可以设置GrassViewModelUnitViewModel Then create a DataTemplate for each one. 然后为每个创建一个DataTemplate For example: 例如:

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

The for showing the elements in a grid you may use a ListBox with a Grid as items panel, some like this: 用于显示网格中的元素的,您可以将ListBoxGrid as Items面板一起使用,如下所示:

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

Then you only need to create the AllItemsCollection in your view model with all the elements that you want. 然后,您只需要在视图模型中使用所需的所有元素创建AllItemsCollection You can handler the click event using behaviors, or creating a UserControl for the grass (and controlling the click event inside): 您可以使用行为来处理click事件,或为草创建UserControl(并在内部控制click事件):

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

Hope helps... 希望可以帮助...

If your following MVVM then you can attach a property to the label as below. 如果您使用以下MVVM,则可以按如下所示将属性附加到标签。 You can attache this behavior any control that derives from UIElement 您可以将此行为附加到任何从UIElement派生的控件

Create a Attached property for MouseClick 为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);
                    }
                }
            }
        }
    }
}

In you Xaml attache the Command of your viewModel as below 在您的Xaml中,如下附加viewModel的命令

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM