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

时间:2011-03-16 11:50:36

标签: c# wpf design-patterns xaml

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

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. 如何正确处理'设置' 属性?用户做什么 切换设置的类型?

3 个答案:

答案 0 :(得分:1)

我相信您正在寻找的是DataBinding和DataTemplating的组合。 DataTemplating允许您为不同的业务对象定义不同的可视元素(在本例中为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

答案 1 :(得分:0)

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

this.DataContext=MyObject;

定义单个元素的绑定。

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

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

答案 2 :(得分:0)

  1. 如果用户点击“确定”,如何使数据绑定不修改对象?
  2. 创建MyObject实例的副本。在Result属性get方法中,如果用户点击取消返回副本(返回未更改的副本),或者如果用户点击OK,则返回已更改的MyObject实例。

    1. 如何正确处理'设置'属性?用户切换设置类型时该怎么办?
    2. 问题是什么?