【问题标题】:Save ObservableCollection to textfile when closing MainWindow关闭 MainWindow 时将 ObservableCollection 保存到文本文件
【发布时间】:2014-06-25 06:45:18
【问题描述】:

我是 C# 和 WPF 的新手,并且已经完成了编写警报的任务。现在我有一个问题,我必须在关闭主窗口时将设置的时间保存到一个文本文件中。

时间存储在 Reminder 类型的 ObservableCollection 中,这是我自己编写的一个类,并将警报的时间和名称存储为字符串。

public override string ToString()
    {            
        return ReminderName + " " + ReminderTime.ToString("HH:mm");
    }

我的保存功能是这样的:

...
public RelayCommand<object> SaveAllTimes { get; set; }
...
public MainWindowModel()
{
...
SaveAllTimes = new RelayCommand<object>(SaveReminders, CanSaveReminders);
...
}

private void SaveReminders(object sender)
    {

        StreamWriter writer = new StreamWriter("time.txt");
            foreach (Reminder time in Reminders)
            {
                writer.WriteLine(time.ToString());
            }
    }

现在我怎样才能将视图绑定到这个函数,当用户关闭它时它会被执行?

我的观点是这样的:

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

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="3*" />
        <RowDefinition Height="1*" />
    </Grid.RowDefinitions>

    <ListBox Name="Liste" ItemsSource="{Binding Reminders}" Margin="10" Grid.Row="0">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox Content="{Binding}" IsChecked="{Binding Active}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <Button Command="{Binding SaveTime}" Content="Add Reminder" Margin="10" Grid.Column="1"/>
        <Button Margin="10" Content="Stop" Command="{Binding DeleteTime}" 
            CommandParameter="{Binding ElementName=Liste,Path=SelectedItem}" />
    </Grid>     

</Grid>
</Window>

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    这是我使用纯 MVVM 的方法,不依赖于任何其他提供者

    xaml

    <Window x:Class="CSharpWPF.ViewModel"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:l="clr-namespace:CSharpWPF"
            l:MyEventHandler.ClosingCommand="{Binding SaveAllTimes}">
    </Window>
    

    MyEventHandler 类

    namespace CSharpWPF
    {
        public class MyEventHandler
        {
            public static ICommand GetClosingCommand(DependencyObject obj)
            {
                return (ICommand)obj.GetValue(ClosingCommandProperty);
            }
    
            public static void SetClosingCommand(DependencyObject obj, ICommand value)
            {
                obj.SetValue(ClosingCommandProperty, value);
            }
    
            // Using a DependencyProperty as the backing store for ClosingCommand.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty ClosingCommandProperty =
                DependencyProperty.RegisterAttached("ClosingCommand", typeof(ICommand), typeof(MyEventHandler), new PropertyMetadata(OnClosingCommandChanged));
    
            private static void OnClosingCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                Window window = d as Window;
                window.Closing += (s, ee) => GetClosingCommand(d).Execute(ee);
            }
        }
    }
    

    所以整个想法是通过Attached Properties 将事件路由到绑定命令,您可以根据需要创建更多处理程序

    【讨论】:

      【解决方案2】:

      在您的代码中,您正在创建视图和视图模型。从我的角度来看(这部分肯定是基于意见的)你应该在那里实现你的 On-Exit 代码,因为你的数据保存是在过程的结束,而不是视图的结束。当您的 MainWindow 运行时,您可以调用 viewmodel 方法来保存所有相关数据。

      如果您确实希望在关闭视图而不是结束程序时拥有它,您可以走两条路:黑暗的一面,通过为窗口编写代码隐藏 OnClose 处理程序。不要告诉任何人我说过。这不是 WPF 风格。或者通过为您的窗口实现关闭行为来获得正确的路径。这对于单个帖子来说太宽泛了,您应该查找 WPF、View 和 Behavior,您会发现很多针对不同行为的教程。

      【讨论】:

        【解决方案3】:

        您可以使用交互性将Closing 事件绑定到您的Command,如下所示

        <Window xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Closing">
                    <i:InvokeCommandAction Command="{Binding SaveAllTimes }"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Window>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-20
          • 2013-08-07
          • 1970-01-01
          • 2014-11-25
          • 2013-04-13
          • 1970-01-01
          • 2013-02-09
          • 2012-09-27
          相关资源
          最近更新 更多