我应该使用什么设计模式来制作这样的对话框?

发布于 2024-10-21 23:41:15 字数 3546 浏览 0 评论 0原文

我想开发用于编辑利用多态性的对象的对话框。目前我正在使用此模式:

MyObject.cs:

using System;

namespace WpfApplication3
{
    public class MyObject
    {
        public string Title { get; set; }
        public MySettings Settings { get; set; }
    }

    public abstract class MySettings
    {
        public abstract string GetSettingsString();
    }

    public class MyBoolSettings : MySettings
    {
        public bool BoolSetting { get; set; }

        public override string GetSettingsString()
        {
            return "BoolSetting = " + BoolSetting;
        }
    }

    public class MyStringSettings : MySettings
    {
        public string StringSetting { get; set; }

        public override string GetSettingsString()
        {
            return "StringSetting = " + StringSetting;
        }
    }
}

MainWindow.xaml:

<Window x:Class="WpfApplication3.EditMyObjectDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="EditMyObjectDialog" Height="350" Width="350">
    <StackPanel Margin="20">
        <TextBlock Text="Title" />
        <TextBox Name="txtTitle" />
        <RadioButton Name="rdBoolSettings" Content="BoolSettings" IsChecked="True" Margin="0, 20, 0, 0" />
        <CheckBox Name="chBool" Content="True" Margin="20, 0, 0, 20" />
        <RadioButton Name="rdStringSettings" Content="StringSettings" />
        <TextBox Name="txtString" Margin="20, 0, 0, 20"/>
        <Button Content="OK" Click="OK_click" />
        <Button Content="Cancel" Click="Cancel_click" Margin="0, 10" />
    </StackPanel>
</Window>

MainWindow.xaml.cs:

using System.Windows;

namespace WpfApplication3
{
    public partial class EditMyObjectDialog : Window
    {
        public MyObject Result { get; set; }

        public EditMyObjectDialog(MyObject objectToEdit)
        {
            InitializeComponent();
            txtTitle.Text = objectToEdit.Title;
            if (objectToEdit.Settings is MyBoolSettings)
            {
                rdBoolSettings.IsChecked = true;
                chBool.IsChecked = (objectToEdit.Settings as MyBoolSettings).BoolSetting;
            }
            if (objectToEdit.Settings is MyStringSettings)
            {
                rdBoolSettings.IsChecked = true;
                txtString.Text = (objectToEdit.Settings as MyStringSettings).StringSetting;
            }
        }

        private void OK_click(object sender, RoutedEventArgs e)
        {
            Result = new MyObject() { Title = txtTitle.Text };
            if (rdBoolSettings.IsChecked == true) 
                Result.Settings = new MyBoolSettings() { BoolSetting = chBool.IsChecked == true };
            if (rdStringSettings.IsChecked == true)
                Result.Settings = new MyStringSettings() { StringSetting = txtString.Text };
            DialogResult = true;
        }

        private void Cancel_click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
        }
    }
}

ExternalCode:

var f = new EditMyObjectDialog(myObject);
if (f.ShowDialog() == true)
    myObject = f.Result;

我相信有更好的设计模式使用数据绑定等。所以基本上我有两个问题。

  1. 如何让数据绑定不 修改对象直到用户点击“确定”?
  2. 如何正确处理“设置” 财产?用户使用时应该做什么 切换设置的类型?

I want to develop dialog for editing objects that make use of polymorphism. Currently I'm using this pattern:

MyObject.cs:

using System;

namespace WpfApplication3
{
    public class MyObject
    {
        public string Title { get; set; }
        public MySettings Settings { get; set; }
    }

    public abstract class MySettings
    {
        public abstract string GetSettingsString();
    }

    public class MyBoolSettings : MySettings
    {
        public bool BoolSetting { get; set; }

        public override string GetSettingsString()
        {
            return "BoolSetting = " + BoolSetting;
        }
    }

    public class MyStringSettings : MySettings
    {
        public string StringSetting { get; set; }

        public override string GetSettingsString()
        {
            return "StringSetting = " + StringSetting;
        }
    }
}

MainWindow.xaml:

<Window x:Class="WpfApplication3.EditMyObjectDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="EditMyObjectDialog" Height="350" Width="350">
    <StackPanel Margin="20">
        <TextBlock Text="Title" />
        <TextBox Name="txtTitle" />
        <RadioButton Name="rdBoolSettings" Content="BoolSettings" IsChecked="True" Margin="0, 20, 0, 0" />
        <CheckBox Name="chBool" Content="True" Margin="20, 0, 0, 20" />
        <RadioButton Name="rdStringSettings" Content="StringSettings" />
        <TextBox Name="txtString" Margin="20, 0, 0, 20"/>
        <Button Content="OK" Click="OK_click" />
        <Button Content="Cancel" Click="Cancel_click" Margin="0, 10" />
    </StackPanel>
</Window>

MainWindow.xaml.cs:

using System.Windows;

namespace WpfApplication3
{
    public partial class EditMyObjectDialog : Window
    {
        public MyObject Result { get; set; }

        public EditMyObjectDialog(MyObject objectToEdit)
        {
            InitializeComponent();
            txtTitle.Text = objectToEdit.Title;
            if (objectToEdit.Settings is MyBoolSettings)
            {
                rdBoolSettings.IsChecked = true;
                chBool.IsChecked = (objectToEdit.Settings as MyBoolSettings).BoolSetting;
            }
            if (objectToEdit.Settings is MyStringSettings)
            {
                rdBoolSettings.IsChecked = true;
                txtString.Text = (objectToEdit.Settings as MyStringSettings).StringSetting;
            }
        }

        private void OK_click(object sender, RoutedEventArgs e)
        {
            Result = new MyObject() { Title = txtTitle.Text };
            if (rdBoolSettings.IsChecked == true) 
                Result.Settings = new MyBoolSettings() { BoolSetting = chBool.IsChecked == true };
            if (rdStringSettings.IsChecked == true)
                Result.Settings = new MyStringSettings() { StringSetting = txtString.Text };
            DialogResult = true;
        }

        private void Cancel_click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
        }
    }
}

ExternalCode:

var f = new EditMyObjectDialog(myObject);
if (f.ShowDialog() == true)
    myObject = f.Result;

I belive there is much better design pattern that uses data binding etc. So basically I have two questions.

  1. How to make data binding not to
    modify object until user hits 'OK'?
  2. How to correctly handle 'Settings'
    property? What to do when user
    switches setting's type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苍景流年 2024-10-28 23:41:15

我相信您正在寻找的是数据绑定和数据模板的组合。 DataTemplated 将允许您为不同的业务对象定义不同的可视元素(在本例中为 MyBooleanSettingsMyStringSettings)。DataBinding 将允许可视元素更新并更新我的数据 属性

示例(xaml):

<Window DataContext={Binding RelativeSource={RelativeSource Self}}">
    <Window.Resources>
        <DataTemplate DataType={x:Type local:MyObject}">
            <TextBlock Text={Binding Title}" />
            <ContentPresenter Content="{Binding Settings}" />
        </DataTemplate>
        <DataTemplate DataType={x:Type local:MyObject}">
            <TextBox Text={Binding 
        </DataTemplate>
        <DataTemplate DataType={x:Type local:MyBoolSettings}>
            <CheckBox IsChecked="{Binding BoolSetting}" />
        </DataTemplate>
        <DataTemplate DataType={x:Type local:MyStringSettings}>
            <TextBox Text="{Binding StringSetting}" />
        </DataTemplate>
    </Window.Resources>
    <ContentPresenter Content="{Binding ObjectToEdit}" />
</Window>

然后在后面的代码中定义:

public MyObject ObjectToEdit { get; set; }

最后更新您的对象:

public class MySettings : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(sting s)
    {
        if(PropertyChanged != null)
        {
            PropertyChanged(s);
        }
    }
}

public class BoolSettings : MySettings
{
    bool _value;

    bool BoolSetting
    {
        get { return _value; }
        set
        {
            if(_value != value)
            {
                _value = value;
                OnPropertyChanged("BoolSetting");
            }
         }
    }
}

但是,如果您确实需要控制视图和对象同步的时间,则应该使用 UpdateSourceTrigger 相应的绑定。

如果您需要一些额外的阅读,我建议:http ://msdn.microsoft.com/en-us/library/ms752347.aspx

What I believe you're looking for is a combination of DataBinding and DataTemplating. DataTemplating will allow you to define different visual elements for different business objects (in this case MyBooleanSettings and MyStringSettings. DataBinding will allow the visual elements to update and be updated my the data in the business objects.

Example (xaml):

<Window DataContext={Binding RelativeSource={RelativeSource Self}}">
    <Window.Resources>
        <DataTemplate DataType={x:Type local:MyObject}">
            <TextBlock Text={Binding Title}" />
            <ContentPresenter Content="{Binding Settings}" />
        </DataTemplate>
        <DataTemplate DataType={x:Type local:MyObject}">
            <TextBox Text={Binding 
        </DataTemplate>
        <DataTemplate DataType={x:Type local:MyBoolSettings}>
            <CheckBox IsChecked="{Binding BoolSetting}" />
        </DataTemplate>
        <DataTemplate DataType={x:Type local:MyStringSettings}>
            <TextBox Text="{Binding StringSetting}" />
        </DataTemplate>
    </Window.Resources>
    <ContentPresenter Content="{Binding ObjectToEdit}" />
</Window>

Then in the code behind define:

public MyObject ObjectToEdit { get; set; }

Finally update your objects:

public class MySettings : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(sting s)
    {
        if(PropertyChanged != null)
        {
            PropertyChanged(s);
        }
    }
}

public class BoolSettings : MySettings
{
    bool _value;

    bool BoolSetting
    {
        get { return _value; }
        set
        {
            if(_value != value)
            {
                _value = value;
                OnPropertyChanged("BoolSetting");
            }
         }
    }
}

If however you really need to control when the view and object sync you should use the UpdateSourceTrigger property on the corresponding bindings.

If you want some additional reading I recommend: http://msdn.microsoft.com/en-us/library/ms752347.aspx

花开浅夏 2024-10-28 23:41:15

数据绑定很简单。您可以创建 MyObject 的实例并将其分配给 Form 的 DataContext 属性。

this.DataContext=MyObject;

并定义各个元素的绑定。

 <TextBox Name="txtTitle" Text="{Binding Path=Title,Mode=TwoWay }" />

当您在 UI 中进行更改时,将模式设置为两种方式将会影响对象。一种方式将显示值。

DataBinding is Simple . You can create an instance of MyObject and assign it to the DataContext property of the Form.

this.DataContext=MyObject;

And define binding for individual elements.

 <TextBox Name="txtTitle" Text="{Binding Path=Title,Mode=TwoWay }" />

Setting mode as two way will affect the object as you make change in UI. One way will show the values.

热风软妹 2024-10-28 23:41:15
  1. 如何使数据绑定在用户点击“确定”之前不修改对象?

创建 MyObject 实例的副本。在 Result 属性 get 方法中,如果用户点击“取消”(返回未更改的副本),则返回副本,或者如果用户点击“确定”,则返回更改后的 MyObject 实例。

  1. 如何正确处理“Settings”属性?当用户切换设置类型时该怎么办?

有什么问题吗?

  1. How to make data binding not to modify object until user hits 'OK'?

Create a copy of the MyObject instance. In the Result property get method, return copy if user hit cancel (return unchanged copy) or if user hit OK, return the changed MyObject instance.

  1. How to correctly handle 'Settings' property? What to do when user switches setting's type?

Whats the problem?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文