2D grid with selectable items in c# Wforms?

后端 未结 1 424
情书的邮戳
情书的邮戳 2020-12-20 07:56

How can be done a 2D of 10x10 selectable elements each element with text in a windows form? Is there an easy way of doing this?

I need to select some elements in an

相关标签:
1条回答
  • 2020-12-20 08:25

    Posting this as an answer because the OP asked for it:

    <Window x:Class="MiscSamples.GridRobot"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="GridRobot" Height="500" Width="600">
    <DockPanel>
    
        <DockPanel DockPanel.Dock="Top">
            <TextBlock Text="Size:" Margin="2" DockPanel.Dock="Left"/>
            <TextBox Text="{Binding Size}" IsReadOnly="True" DockPanel.Dock="Left" Margin="2" Width="50"/>
            <Slider Maximum="20" Minimum="2" Value="{Binding Size}"/>
        </DockPanel>
    
        <StackPanel DockPanel.Dock="Left" Width="100" Margin="2">
            <TextBlock Text="Route:" TextAlignment="Center" FontWeight="Bold"/>
            <ItemsControl ItemsSource="{Binding Route}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock TextAlignment="Center">
                            <TextBlock.Text>
                                <MultiBinding StringFormat="{}{0:D2},{1:D2}">
                                    <Binding Path="Row"/>
                                    <Binding Path="Column"/>
                                </MultiBinding>
                            </TextBlock.Text>
                        </TextBlock>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>
    
        <Grid>
            <ItemsControl ItemsSource="{Binding Squares}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <UniformGrid Rows="{Binding Size}" Columns="{Binding Size}"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Border BorderBrush="DarkGray" BorderThickness="1">
                            <Button Command="{Binding DataContext.GoToCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
                                    CommandParameter="{Binding}">
                                <Button.Template>
                                    <ControlTemplate>
                                        <Border Background="#05FFFFFF">
                                            <Viewbox>
                                                <TextBlock Text="{Binding PathIndex}" 
                                                TextAlignment="Center" VerticalAlignment="Center"/>
                                            </Viewbox>
                                        </Border>
                                    </ControlTemplate>
                                </Button.Template>
                            </Button>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
            <Canvas>
                <!-- I was about to add the Robot Peg here and animate it -->
            </Canvas>
        </Grid>
    </DockPanel>
    </Window>
    

    Code Behind:

    public partial class GridRobot : Window
    {
        public GridRobot()
        {
            InitializeComponent();
            DataContext = new GridRobotViewModel();
        }
    }
    

    View Model:

    public class GridRobotViewModel: PropertyChangedBase
    {
        private int _size;
        public int Size
        {
            get { return _size; }
            set
            {
                _size = value;
                OnPropertyChanged("Size");
                CreateItems();
            }
        }
    
        private ObservableCollection<GridItem> _squares;
        public ObservableCollection<GridItem> Squares
        {
            get { return _squares ?? (_squares = new ObservableCollection<GridItem>()); }
        }
    
        private ObservableCollection<GridItem> _route;
        public ObservableCollection<GridItem> Route
        {
            get { return _route ?? (_route = new ObservableCollection<GridItem>()); }
        }
    
        private void CreateItems()
        {
            Squares.Clear();
            Route.Clear();
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    Squares.Add(new GridItem() {Row = i, Column = j});
                }
            }
        }
    
        private Command<GridItem> _goToCommand;
        public Command<GridItem> GoToCommand
        {
            get { return _goToCommand ?? (_goToCommand = new Command<GridItem>(Goto){IsEnabled = true}); }
        }
    
        private void Goto(GridItem item)
        {
            if (item.PathIndex == null)
            {
                item.PathIndex = Squares.Max(x => x.PathIndex ?? 0) + 1;
    
                Route.Add(item);    
            }
        }
    }
    

    Data Item:

    public class GridItem: PropertyChangedBase
    {
        public int Row { get; set; }
    
        public int Column { get; set; }
    
        private int? _pathIndex;
        public int? PathIndex
        {
            get { return _pathIndex; }
            set
            {
                _pathIndex = value;
                OnPropertyChanged("PathIndex");
            }
        }
    }
    

    Support Classes for MVVM:

    public class PropertyChangedBase:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            Application.Current.Dispatcher.BeginInvoke((Action) (() =>
                {
                    PropertyChangedEventHandler handler = PropertyChanged;
                    if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
                }));
        }
    }
    
    public class Command<T>: ICommand
    {
        public Action<T> Action { get; set; }
    
        public void Execute(object parameter)
        {
            if (Action != null && parameter is T)
                Action((T)parameter);
        }
    
        public bool CanExecute(object parameter)
        {
            return IsEnabled;
        }
    
        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                if (CanExecuteChanged != null)
                    CanExecuteChanged(this, EventArgs.Empty);
            }
        }
    
        public event EventHandler CanExecuteChanged;
    
        public Command(Action<T> action)
        {
            Action = action;
        }
    }
    

    Result:

    enter image description here

    • Just copy and paste my code in a File -> New Project -> WPF Application and see the results for yourself.
    • You said 10 x 10, but I went a step further and added a Slider to make the grid size customizable.
    • Clicking on any cell will make it be queued as part of the Route.
    • Fully Resolution Independent.
    • I was about to start putting some really nice stuff on it (animations, robot movement represented by an ellipse, Lines for the Path, etc).
    • Forget winforms, it's useless.
    0 讨论(0)
提交回复
热议问题