Is it possible to make a relative binding with the

2019-08-20 09:32发布

问题:

I am new to WPF and MVVM and I have the following question

  1. I have 3 buttons
  2. When I click on one button, it gets an CommandParameter, for example: 0,1
  3. The Command SetBackGround splits the CommandParameter for extract row and column
  4. Now I try the binding with IsSelected that has conditions and Background for setting the Background
  5. The problem is... when I click all the buttons, they set a yellow Background, but I only need the buttons that have the right condition, so..

Do I need to make a different background for each button, or does an other way exist?

Who say.. if this conditions "parameters" set that background to yellow, and the others - not.

Image

ViewModel

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Testing00.Commands;

namespace Testing00.ViewModels
{
    public class ViewModel : INotifyPropertyChanged
    {

        public ICommand SetBackGroundCommand { get; set; }
        bool LeftSelected { get; set; }
        bool RightSelected { get; set; }

        #region Methods
        int row;
        public int Row
        {
            get { return row; }
            set { row = value; }
        }

        int column;
        public int Column
        {
            get { return column; }
            set { column = value; }
        }

        public bool IsSelected
        {
            get
            {
                if (row == 0 && column == 0)
                {
                    return false;
                }
                else
                {

                    return true;
                }
            }
            set
            {
                OnPropertyChanged("IsSelected");
                OnPropertyChanged("Background");
            }
        }

        public string Background
        {
            get
            {
                return IsSelected ? "Yellow" : "Transparent";
            }
        }

        #endregion


        #region Constructor

        public ViewModel()
        {
            SetBackGroundCommand = new RelayCommand(SetBackGround, param => true);
        }

        #endregion

        private void SetBackGround(object obj)
        {
            string[] commandParametters = obj.ToString().Split(',');
            Row = Convert.ToInt32(commandParametters[0]);
            Column = Convert.ToInt32(commandParametters[1]);
            OnPropertyChanged("IsSelected");
            OnPropertyChanged("BackGround");
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }
}

MainWindows

<Window x:Class="Testing00.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:TEST="clr-namespace:Testing00.ViewModels"
        xmlns:local="clr-namespace:Testing00"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <TEST:ViewModel x:Key="testVM"></TEST:ViewModel>
    </Window.Resources>
    <Grid>
        <Button Content="0,0" HorizontalAlignment="Left" Margin="84,109,0,0" VerticalAlignment="Top" Width="79" Height="81"    CommandParameter="0,0" Command="{Binding SetBackGroundCommand, Source={StaticResource testVM}}" Background="{Binding Background, Mode=OneWay, Source={StaticResource testVM}}"    />
        <Button Content="0,1" HorizontalAlignment="Left" Margin="208,109,0,0" VerticalAlignment="Top" Width="79" Height="81" CommandParameter="0,1" Command="{Binding SetBackGroundCommand, Source={StaticResource testVM}}"  Background="{Binding Background, Mode=OneWay, Source={StaticResource testVM}}" />
        <Button Content="0,2" HorizontalAlignment="Left" Margin="341,109,0,0" VerticalAlignment="Top" Width="79" Height="81"  CommandParameter="0,2" Command="{Binding SetBackGroundCommand, Source={StaticResource testVM}}"  Background="{Binding Background, Mode=OneWay, Source={StaticResource testVM}}" />
    </Grid>
</Window>

RelayCommand

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Testing00.Commands
{
    public class RelayCommand : ICommand
    {

        Action<object> _execute;
        Func<object, bool> _canexecute;
        public RelayCommand(Action<object> execute, Func<object, bool> canexecute)
        {
            _execute = execute;
            _canexecute = canexecute;

        }
        public bool CanExecute(object parameter)
        {
            if (_canexecute != null)
            {
                return _canexecute(parameter);
            }
            else
            {
                return false;
            }
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }
}

回答1:

roughly, and with little code being demonstrated (you can find more if you look for ItemsControl) you can do as grek40 said.

your button will be an usercontrol (ucMyButton) with its own viewmodel and its properties.

in your mainview you will add an ItemControl and it will include a collection of buttons (ObservableCollection<MyButtonViewModel> MyButtons { ..... })

then each MyButtonViewModel will be a separate button with its own Background property so each button can be set separately

<ItemsControl x:Name="itmWrapPanel" 
            ItemsSource="{Binding MyButtons, UpdateSourceTrigger=PropertyChanged}"  

            ScrollViewer.CanContentScroll="True"
            ScrollViewer.VerticalScrollBarVisibility="Auto"
            ScrollViewer.HorizontalScrollBarVisibility="Auto"
            >
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal"  
                    Background="White" 
                    AllowDrop="True" 
                    Width="{Binding ActualWidth, ElementName=itmWrapPanel}" 
                    Height="{Binding ActualHeight, ElementName=itmWrapPanel}"  />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate  >
            <local:ucMyButton  />

        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>


标签: wpf mvvm