0

我正在尝试构建一个遵循最佳 MVVM 实践的 WPF 应用程序进行演示,但我很快发现我不确定最佳实践是什么!:)

我现在有一个具体问题。

作为一些背景(如果它显示在我的片段中),我使用 MVVMLight(因为它的 PCL 可移植性),NInject 作为容器,使用 Prism 作为其区域支持。

看法

[片段]

        <!-- bind the selection of a new item to the view model -->
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <cmd:EventToCommand Command="{Binding SelectTypeCommand}"
                                    CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}, Path=SelectedItem}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>

        <!-- visual template of the list items -->
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <TextBlock>Name: <Run Text="{Binding Name}"></Run></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

    <!-- detail view -->
    <Grid Grid.Row="0" Grid.Column="1">
        <StackPanel Orientation="Vertical" Margin="5">
            <Label>ID</Label>
            <TextBox Text="{Binding SelectedType.Id, Mode=TwoWay}" IsEnabled="False"></TextBox>
            <Label>Name</Label>
            <TextBox Text="{Binding SelectedType.Name, Mode=TwoWay}"></TextBox>
        </StackPanel>
    </Grid>

视图模型

[片段]

public class ClientTypesViewModel : BaseUpdateableViewModel
{
    private ThingType selectedtype = null;

    public ThingType SelectedType
    {
        get { return selectedtype; }
        protected set { Set(() => SelectedType, ref selectedtype, value); }
    }

    private RelayCommand<ThingType> selecttypecommand;

    public RelayCommand<ThingType> SelectTypeCommand
    {
        get { return selecttypecommand ?? (selecttypecommand = new RelayCommand<ThingType>(ExecuteSelectTypeCommand)); }
    }

    private async void ExecuteSelectTypeCommand(ThingType newtype)
    {
        // Save the type if required - goes away to a service (HttpClient...)
        if (!await SaveSelectedType())
        {
            // Cancel navigation?
            return;
        }

        // Update the selected type
        this.SelectedType = newtype;
    }

    private async Task<bool> SaveSelectedType()
    {
            if (selectedtype == null) return true;
            if (!selectedtype.IsDirty) return true;

            bool? result = await navigationservice.AskConfirmation("Do you want to save this client type?", "Yes", "No", "Cancel");

            if (result == null) 
                return false; // cancel

            if (!result.Value)
            {
                selectedtype.MakeClean();
                return true; // ignore changes
            }

            // Ask the data service to save for us
            await dataservice.UpdateClientType(selectedtype);
            selectedtype.MakeClean();
            return true;
    }
}

Two columns, left hand holds a list of entities that when one is selected, the details column on the right updates to allow view/edit. 如果用户在右侧面板中编辑了实体,我将其视图模型标记为“脏”。

当用户尝试在左栏中选择不同的实体时,我希望能够(在 ViewModel 中)询问用户是否要离开并丢失更改,或者是否要保存更改.

这我可以呈现(通过导航服务),但我不知道如何在视图模型中真正使​​“取消”工作,这让我重新思考我的整个方法。

如果我在两个方向上绑定,SelectedItem那么我认为我不能在RaisePropertyChanged触发之前更新基础字段 - 但是因为我需要调用异步代码来持久化我的实体(HttpClient),所以我不能在属性设置器。

所以我已经完成了上述操作,如果没有可怕的黑客攻击,我就无法真正开始工作。

有没有更好的通用解决方案,我只是没有看到?或者更好的例子?

编辑

我已经意识到我不清楚我在这里想要完成什么。问题不在于如何恢复所做的更改,正如@Alan 正确指出的那样,有一些标准的方法可以解决这个问题。

我在尝试更改左窗格中的选定类型时向用户询问以下内容:

您要保存此类型吗?

[是] - 保存并允许导航

[否] - 还原更改并允许导航

[取消] - 保留更改并取消导航

它的[取消]我不知道如何正确处理。

4

1 回答 1

0

我相信您的答案是通过实施 IConfirmNavigationRequest 在 Prism 书中?

确认或取消导航

您会经常发现在导航操作过程中需要与用户进行交互,以便用户确认或取消它。例如,在许多应用程序中,用户可能会在输入或编辑数据的过程中尝试导航。在这些情况下,您可能想询问用户是否要在继续导航离开页面之前保存或丢弃已输入的数据,或者用户是否要完全取消导航操作。Prism 通过 IConfirmNavigationRequest 接口支持这些场景。

来自 Prism 书 8:导航

于 2013-06-19T14:20:15.603 回答