简体   繁体   English

C#用户必须向WPF和按钮添加多个按钮必须保持

[英]C# User Must Add Multiple Buttons to WPF and Buttons Must Persist

I am attempting to create a program in which the User can create multiple profiles. 我正在尝试创建一个程序,用户可以在其中创建多个配置文件。 These profiles can be accessed via buttons that appear as each profile is completed. 可以通过每个配置文件完成时显示的按钮访问这些配置文件。

My problem: 我的问题:

  • I have no clue how to make the created buttons persist after the program is exited(I need to save the buttons?) 我不知道在程序退出后如何使创建的按钮保持不变(我需要保存按钮?)

Visually, this is program's process: 1) Enter your information, click continue 2) View a display page of what you entered, click done. 在视觉上,这是程序的过程:1)输入您的信息,单击继续2)查看您输入的内容的显示页面,单击完成。 3) This adds a button to the final window, the button of course takes you to 4) Your profile you just created. 3)这会在最后一个窗口添加一个按钮,按钮当然会带您到4)您刚刚创建的配置文件。

您可以通过输入信息开始表单。在此输入图像描述在此输入图像描述在此输入图像描述

After this, the program ends and nothing is saved. 在此之后,程序结束并且不保存任何内容。 I'm fairly new to c# and am quite confused on how to "save" multiple buttons without massively complicating the code. 我对c#很新,我对如何“保存”多个按钮而不会使代码大量复杂化感到困惑。 I'm a complete noob to c# and have a little Java experience. 我是c#的完全菜鸟,并且有一点Java经验。 Am I going about this correctly? 我正确地谈到这个吗? I'm pretty sure its possible but have no idea to go about it. 我很确定它可能但不知道如何去做。

I will include my code below. 我将在下面包含我的代码。 I'm working in visual studios 2012. any help would be appreciated! 我在视觉工作室2012工作。任何帮助将不胜感激! MainWindow XAML: MainWindow XAML:

<Window x:Class="VendorMain.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

<Grid>
    <Label Content="FirstName" HorizontalAlignment="Left" Margin="63,45,0,0" VerticalAlignment="Top"/>
    <Label Content="LastName" HorizontalAlignment="Left" Margin="63,71,0,0" VerticalAlignment="Top"/>
    <Label Content="Image" HorizontalAlignment="Left" Margin="63,102,0,0" VerticalAlignment="Top"/>

    <Image Name="imgPhoto" Stretch="Fill" Margin="63,133,303,69"></Image>
    <Button Name="UploadImageButton" Content="Upload Image" HorizontalAlignment="Left" Margin="130,105,0,0" VerticalAlignment="Top" Width="84" Click="UploadImageButton_Click"/>

    <TextBox Name="AssignFirstName" Text="{Binding SettingFirstname}" HorizontalAlignment="Left" Height="23" Margin="130,48,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" />
    <TextBox Name="AssignLastName" Text="{Binding SettingLastName}" HorizontalAlignment="Left" Height="23" Margin="130,75,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>

    <Button Name="ContinueToDisplayWindow" Content="Continue" HorizontalAlignment="Left" Margin="409,288,0,0" VerticalAlignment="Top" Width="75" Click="ContinueToDisplayWindow_Click" />
</Grid>

MainWindow Code: MainWindow代码:

namespace VendorMain
{
    public partial class MainWindow : Window
    {
    public MainWindow()
    {
        InitializeComponent();
    }

    private void UploadImageButton_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog op = new OpenFileDialog();
        op.Title = "Select a picture";
        op.Filter = "All supported graphics|*.jpg;*.jpeg;*.png|" +
            "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
            "Portable Network Graphic (*.png)|*.png";
        if (op.ShowDialog() == true)
        {
            imgPhoto.Source = new BitmapImage(new System.Uri(op.FileName));
            //SettingImage.Source = imgPhoto.Source; 
        }
    }

    private void ContinueToDisplayWindow_Click(object sender, RoutedEventArgs e)
    {
        DisplayPage displaypg = new DisplayPage();
        displaypg.DpFirstName.Content = AssignFirstName.Text;
        displaypg.DpLastName.Content = AssignLastName.Text;
        displaypg.DpImage.Source = imgPhoto.Source;
        displaypg.Show();
    }      
}
}

DisplayPage XAML: DisplayPage XAML:

 <Window x:Class="VendorMain.DisplayPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="DisplayPage" Height="300" Width="525">
<Grid>
    <Label Name="DpFirstName" Content="{Binding getFirstNamePermenent}" HorizontalAlignment="Left" Margin="86,55,0,0" VerticalAlignment="Top"/>
    <Label Name="DpLastName" Content="{Binding getLastNamePermenent}" HorizontalAlignment="Left" Margin="87,80,0,0" VerticalAlignment="Top"/>
    <Image Name="DpImage" HorizontalAlignment="Left" Height="100" Margin="94,111,0,0" VerticalAlignment="Top" Width="100"/>
    <Button Name="ButtonizeThisProfile_Button" Content="Done" HorizontalAlignment="Left" Margin="420,238,0,0" VerticalAlignment="Top" Width="75" Click="ButtonizeThisProfile_Button_Click"/>
</Grid>

DisplayPage Code: DisplayPage代码:

namespace VendorMain
{
/// <summary>
/// Interaction logic for DisplayPage.xaml
/// </summary>
public partial class DisplayPage : Window
{
    public Button bot1;

    public DisplayPage()
    {
        InitializeComponent();
    }

    private void newBtn_Click(object sender, RoutedEventArgs e)
    {
        carryToFinalView();
    }

    private void ButtonizeThisProfile_Button_Click(object sender, RoutedEventArgs e)
    {
        UserProfiles uPro = new UserProfiles();

        System.Windows.Controls.Button newBtn = new Button();
        newBtn.Content = "Person1";
        newBtn.Name = "NewProfileButtonAccess";
        newBtn.Click += new RoutedEventHandler(newBtn_Click);
        uPro.ButtonArea.Children.Add(newBtn);
        uPro.Show();
    }

    public void carryToFinalView()
    {
        DisplayPage displaypg = new DisplayPage();
        displaypg.DpFirstName.Content = DpFirstName.Content;
        displaypg.DpLastName.Content = DpLastName.Content;
        displaypg.DpImage.Source = DpImage.Source;
        displaypg.Show();
    }
}
}

UserProfile XAML: UserProfile XAML:

<Window x:Class="VendorMain.UserProfiles"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="UserProfiles" Height="300" Width="525">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width=".8*" />
        <ColumnDefinition Width="2*"/>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="6*"/>
        <RowDefinition Height="11*"/>
    </Grid.RowDefinitions>

    <Label Content="User Profiles: " HorizontalAlignment="Left" Margin="37,47,0,0" VerticalAlignment="Top"/>

    <StackPanel Name="ButtonArea" Grid.Column="2" Grid.Row="2">

    </StackPanel>
    <Button Name="AddAnotherProfileButton" Content="Button" HorizontalAlignment="Left" Margin="35,146,0,0" Grid.Row="1" VerticalAlignment="Top" Width="75" Click="AddAnotherProfileButton_Click"/>

</Grid>

UserProfile Code: UserProfile代码:

namespace VendorMain
{

public partial class UserProfiles : Window
{
    public UserProfiles()
    {
        InitializeComponent();
    }

    private void AddAnotherProfileButton_Click(object sender, RoutedEventArgs e)
    {
        MainWindow mw = new MainWindow();
        mw.Show();
    }
}
}

As a self proclaimed 'noob', I fear that you won't receive an answer here. 作为一个自称为“noob”的人,我担心你不会在这里得到答案。 I certainly don't have time to repeatedly come back to answer a whole continuing stream of related questions. 我当然没有时间反复回来回答一连串相关的问题。 I also don't have time to provide you with a complete solution. 我也没时间为您提供完整的解决方案。 However, I am happy to provide you with sort of 'pseudo code' to at least point you in the right direction... you will have to do a lot of this yourself. 但是,我很高兴为您提供一些“伪代码”,至少指出您正确的方向......您不得不自己做很多事情。

So first things first, as mentioned in a comment, although it is possible, we don't generally save the UI Button objects, but instead we save the data that relates to the user profiles. 所以首先第一件事情,在留言中提到,尽管有可能 ,我们一般不保存UI Button的对象,而是我们保存涉及用户配置文件中的数据。 Therefore, if you haven't done this already, create a User class that has all of the relevant properties. 因此,如果您尚未执行此操作,请创建具有所有相关属性的User类。 Implement the INotifyPropertyChanged Interface in it and add the SerializableAttribute to the class definition... this will enable you to save this class type as binary data. 在其中实现INotifyPropertyChanged Interface并将SerializableAttribute添加到类定义中...这将使您能够将此类类型保存为二进制数据。

Next, in your UI, don't add each Button in xaml... there's a better way. 接下来,在您的UI中,不要在xaml中添加每个Button ...这是一种更好的方法。 One way or another, add a collection property of type User or whatever your class is called, and set this as the ItemsSource of a ListBox . 无论如何,添加User类型的集合属性或您调用的类,并将其设置为ListBoxItemsSource The idea here is to add a DataTemplate for your User type which will display each of the User items in the collection as a Button : 这里的想法是添加DataTemplate你的User类型,这将显示每个的User的集合作为一个在项目Button

<DataTemplate x:Key="UserButtonTemplate" DataType="{x:Type DataTypes:User}">
    <Button Text="{Binding Name}" Width="75" Click="AddAnotherProfileButton_Click" />
</DataTemplate>

You can find out more about DataTemplate s in the Data Templates article . 您可以在“ 数据模板”一文中找到有关DataTemplate的更多信息。

Implementing this collection allows you to have and display any number of user profiles in your UI, rather than being restricted by screen size as your original example would be. 通过实现此集合,您可以在UI中显示和显示任意数量的用户配置文件,而不是像原始示例那样受屏幕大小的限制。

Now finally, on to saving the data... this can be achieved relatively simply using the following code: 现在最后,保存数据......这可以通过以下代码相对简单地实现:

try
{
    using (Stream stream = File.Open("ProfileData.bin", FileMode.Create))
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        binaryFormatter .Serialize(stream, usersList);
    }
}
catch { }

One thing to note is that WPF wants us to use the ObservableCollection<T> class when displaying data in the UI, but this class causes problems when serializing data with this method... therefore, you will need to convert your ObservableCollection<T> to a List<T> or similar. 需要注意的一点是,WPF要求我们在UI中显示数据时使用ObservableCollection<T>类,但是当使用此方法序列化数据时,此类会导致问题...因此,您需要转换ObservableCollection<T>List<T>或类似的。 However, this can be easily achieved: 但是,这很容易实现:

List<User> usersList = users.ToList();

You can find out how to de-serialize your data from the C# Serialize List tutorial. 您可以从C#Serialize List教程中了解如何反序列化数据。 You would deserialize (or load the data from the saved file) each time your application starts and re-save the file each time the program closes. 每次应用程序启动时,您都会反序列化(或从保存的文件中加载数据),并在每次程序关闭时重新保存文件。 You can add an event handler to the Application.Deactivated Event or the Window.Closing which gets called when the application closes, so you can put your code to save the file in there. 您可以向Application.Deactivated事件添加事件处理程序,也可以在应用程序关闭时调用Window.Closing ,这样您就可以将代码保存在那里。

Well, I took longer and wrote more than I had expected, so I hope that helps. 好吧,我花了更长的时间写了比我想象的更多,所以我希望有所帮助。

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

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