简体   繁体   中英

Replace a button with a picture when clicked and then create a new button on top of picture in WPF

I am wanting to create a small program that would let me select from a few images of interconnecting pieces to create what is essentially a path. That idea would be to have a starting piece with a button to where you could connect the next piece of the path. When clicked, this button would offer up a selection of the options that can be placed there and then the selected image would be placed and the button moved to the new end of the path.

My problem is that my c# experience is so far limited to static UI and manipulating text fields or entire new windows. I don't have a clue about where to start to make a UI in which buttons are moved and images are placed after the initial start of the program. I thought maybe using the grid control and some code to manipulate it might be the answer, but really don't know the commands to do such. I have been using WPF for my previous programs, and assume it would still be viable in this case.

Would anyone be able to point me in the right direction to figuring out how to dynamically control a section of the program's window in order to accomplish my goal? I am sorry for the semi-vague question but this is well out of my wheelhouse as a still very new hobbyist programmer.

Here's a quick, rather crude example, but it shows some basics of adding and positioning controls at runtime.

Things to note:

  • Add controls to a Canvas if you want to be able to position x,y explicitly.
  • I used UserControls for location items, and just added instances
  • If you're building a game, and if it's any significant size and complexity, don't use WPF. I've been there, done that, built a full multiplayer space arcade/action game on it. It's too slow for games.

Here's the code dump below.

//PathBuilding.xaml

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TravianResourceProd" x:Class="TravianResourceProd.PathBuilding"
        Title="PathBuilding" Height="466.377" Width="621.509">
    <Grid x:Name="drawingGrid"  Background="#FFC2C2C2" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="0*"/>
        </Grid.ColumnDefinitions>
        <Canvas Background="#FFB3B3B3" Margin="0,0,0,-0.377" x:Name="DrawCanvas" MouseMove="DrawCanvas_MouseMove" MouseUp="Grid_MouseUp">
            <local:ActiveLocation x:Name="primarySegment" HorizontalAlignment="Left" VerticalAlignment="Top" Loaded="ActiveLocation_Loaded" Canvas.Left="67" Canvas.Top="98"/>

        </Canvas>
    </Grid>
</Window>

//PathBuilding.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace TravianResourceProd
{
    /// <summary>
    /// Interaction logic for PathBuilding.xaml
    /// </summary>
    public partial class PathBuilding : Window
    {
        public PathBuilding()
        {
            InitializeComponent();
            _ConnectorLine = new Line();
            _ConnectorLine.Stroke = new SolidColorBrush(Colors.DarkBlue);
            _ConnectorLine.Visibility = System.Windows.Visibility.Hidden;
            _locationSelector = new LocationOptions();
            _locationSelector.Visibility = System.Windows.Visibility.Hidden;
            DrawCanvas.Children.Add(_ConnectorLine);
            DrawCanvas.Children.Add(_locationSelector);

        }

        private Line _ConnectorLine;
        private bool _AddMode = false;


        private LocationOptions _locationSelector;

        private void ActiveLocation_Loaded(object sender, RoutedEventArgs e)
        {
            primarySegment.btnAddSegment.Click += (object sender1, RoutedEventArgs e1) =>
            {
                //show the type selector
                _locationSelector.Visibility = System.Windows.Visibility.Visible;
                var loc = _locationSelector.TransformToAncestor(drawingGrid)
                          .Transform(new Point(0, 0));
                Canvas.SetLeft(_locationSelector, Mouse.GetPosition(DrawCanvas).X + 80);
                Canvas.SetTop(_locationSelector, Mouse.GetPosition(DrawCanvas).Y - 50);

            };
            _locationSelector.btnTypeOne.Click += (object s, RoutedEventArgs e2) =>
            {
                _AddMode = true;
                _ConnectorLine.Visibility = System.Windows.Visibility.Visible;
                _locationSelector.Visibility = System.Windows.Visibility.Hidden;
            };
        }

        private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (!_AddMode)
                return;
            _AddMode = false;
            _ConnectorLine.Visibility = System.Windows.Visibility.Hidden;

            //Add the one we picked
            var oldLoc = new OldLocation();
            Canvas.SetLeft(oldLoc, Canvas.GetLeft(primarySegment));
            Canvas.SetTop(oldLoc, Canvas.GetTop(primarySegment));
            DrawCanvas.Children.Add(oldLoc);

            //Add a line connecting old to new
            var newestLine = new Line();
            newestLine.Visibility = System.Windows.Visibility.Visible;

            newestLine.Stroke = new SolidColorBrush(Colors.Brown);

            newestLine.X1 = _ConnectorLine.X1;
            newestLine.Y1 = _ConnectorLine.Y1;
            newestLine.X2 = _ConnectorLine.X2 + 40;
            newestLine.Y2 = _ConnectorLine.Y2 + 50;
            DrawCanvas.Children.Add(newestLine);

            //Move the active/primary to the new location
            Canvas.SetLeft(primarySegment, e.GetPosition(this).X);
            Canvas.SetTop(primarySegment, e.GetPosition(this).Y);

        }

        private void DrawCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            try
            {//reposition the line going from active location to mouse
                _ConnectorLine.X1 = Canvas.GetLeft(primarySegment) + 70;
                _ConnectorLine.Y1 = Canvas.GetTop(primarySegment) + 50;
                _ConnectorLine.X2 = e.GetPosition(this).X - 5;
                _ConnectorLine.Y2 = e.GetPosition(this).Y - 5;
            }
            catch (Exception)
            {
            }
        }
    }
}

//LocationOptions.xaml

<UserControl x:Class="TravianResourceProd.LocationOptions"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" Height="109.359" Width="117.057">
    <Grid Margin="0,0,-0.17,0.094">
        <Button x:Name="btnTypeOne" Content="Type One" HorizontalAlignment="Left" VerticalAlignment="Top" Width="117" Height="33" Margin="0,0,-0.17,0"  />
        <Button x:Name="btnTypeTwo" Content="Type Two" HorizontalAlignment="Left" VerticalAlignment="Top" Width="117" Margin="0,38,-0.17,0" Height="33"  />

    </Grid>
</UserControl>

//OldLocation.xaml

<UserControl x:Class="TravianResourceProd.OldLocation"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" Height="80" Width="80">
    <Grid>
        <Ellipse Stroke="#FF686868" StrokeThickness="8">
            <Ellipse.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF373737" Offset="1"/>
                    <GradientStop Color="#FF929292"/>
                </LinearGradientBrush>
            </Ellipse.Fill>
        </Ellipse>

    </Grid>
</UserControl>

//ActiveLocation.xaml

<UserControl x:Class="TravianResourceProd.ActiveLocation"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" Height="80" Width="80">
    <Grid>
        <Ellipse Stroke="#FF1A9000" StrokeThickness="6">
            <Ellipse.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF62745E" Offset="1"/>
                    <GradientStop Color="#FF929292"/>
                </LinearGradientBrush>
            </Ellipse.Fill>
        </Ellipse>
        <Button x:Name="btnAddSegment" Content="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="20" Height="22" FontSize="30" Margin="60,30,-0.302,0"/>

    </Grid>
</UserControl>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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