0

我正在尝试创建一个程序,用户可以在其中创建多个配置文件。这些配置文件可以通过每个配置文件完成时出现的按钮访问。

我的问题:

  • 我不知道如何在程序退出后使创建的按钮持续存在(我需要保存按钮吗?)

从视觉上看,这是程序的过程: 1) 输入您的信息,单击继续 2) 查看您输入的内容的显示页面,单击完成。3) 这会在最终窗口中添加一个按钮,该按钮当然会将您带到 4) 您刚刚创建的个人资料。

通过输入信息开始表格。 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

在此之后,程序结束并且没有保存任何内容。我对 c# 相当陌生,并且对如何“保存”多个按钮而不使代码大量复杂化感到很困惑。我完全是 c# 的菜鸟,并且有一点 Java 经验。我这样做对吗?我很确定它是可能的,但不知道该怎么做。

我将在下面包含我的代码。我在视觉工作室 2012 工作。任何帮助将不胜感激!主窗口 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>

主窗口代码:

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

显示页面 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>

显示页面代码:

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

用户配置文件 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>

用户资料代码:

namespace VendorMain
{

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

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

1 回答 1

2

作为一个自称“菜鸟”的人,我担心你不会在这里得到答案。我当然没有时间反复回来回答一连串相关的问题。我也没有时间为您提供完整的解决方案。但是,我很高兴为您提供某种“伪代码”,至少可以为您指明正确的方向……您不得不自己做很多事情。

所以首先,正如评论中提到的,虽然这可能的,但我们通常不保存 UIButton对象,而是保存与用户配置文件相关的数据。因此,如果您还没有这样做,请创建一个User包含所有相关属性的类。在其中实现INotifyPropertyChanged Interface并添加SerializableAttribute到类定义中......这将使您能够将此类类型保存为二进制数据。

接下来,在您的 UI 中,不要Button在 xaml 中添加每个...有更好的方法。一种或另一种方式,添加一个类型的集合属性User或任何你的类被调用的属性,并将其设置为ItemsSourcea 的ListBox。这里的想法是DataTemplate为您的User类型添加一个,它将User集合中的每个项目显示为Button

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

您可以在数据模板文章中找到有关DataTemplates 的更多信息。

实施此集合允许您在 UI 中拥有和显示任意数量的用户配置文件,而不是像原始示例那样受到屏幕大小的限制。

现在最后,保存数据......这可以使用以下代码相对简单地实现:

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

需要注意的一点是,WPF 希望我们ObservableCollection<T>在 UI 中显示数据时使用该类,但是当使用此方法序列化数据时,该类会导致问题......因此,您需要将您的转换ObservableCollection<T>为 aList<T>或类似的。但是,这很容易实现:

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

您可以从C# 序列化列表教程中了解如何反序列化您的数据。您将在每次应用程序启动时反序列化(或从保存的文件中加载数据)并在每次程序关闭时重新保存文件。您可以将事件处理程序添加到Application.Deactivated 事件或应用程序关闭时调用的Window.Closing,以便您可以将代码保存在其中。

好吧,我花了更长的时间,写的比我预期的要多,所以我希望这会有所帮助。

于 2013-08-29T09:55:54.590 回答