2

ninjectを使用してページをロードするMainPageを使用してWPFWebアプリケーションに取り組んでいます。

基本的に、ユーザーが複合キーの値を更新したためにIDが変更されたことをNavigationServiceに通知する方法があるかどうか悩んでいます。

もう少し説明するように頑張ります。私のMultiTagPageにはMultiTagViewModelがあり、(MultiTagDef、Key、Value)で構成されるmultitagvalueを表示します。同じキーとMultiTagDefを持つ他の値を持つDataGridもあります。これらの値の1つをダブルクリックすると、対応するマルチタグ値が代わりに表示されます。

データベースでは、マルチタグ値は複合キー(Multitagdef.Name、key、value)とともに保存されます。したがって、誰かがマルチタグ値を更新すると、IDが変更され(たとえば、(A、B、C)から(A、B、D)に)保存され、ユーザーがデータグリッド内の別のマルチタグ値に進むと(A、B、E)そしておそらくそのオブジェクトを削除してから、navigationserviceは(A、B、D)ではなく(A、B、C)をロードしようとします。

アーキテクチャは、もちろん変更されないID列を持つオブジェクト用に設計されています。残念ながら、この場合、ID列を追加することはできません。それで、誰かがこれを解決する方法の提案を持っていますか?誰かが保存するたびにページをリロードしようとする必要がありますか、それとも現在のオブジェクトがIDを変更したことをNavigationServiceに伝えることができますか?

今、コード:

MainPageから:

public partial class MainPage : IUIService
{
    public static readonly DependencyProperty MainModelProperty = PropertyHelper.Register<MainPage>(x => x.MainModel);

    public MainModel MainModel
    {
        get { return (MainModel)GetValue(MainModelProperty); }
        set { SetValue(MainModelProperty, value); }
    }

    private static readonly ILog log = LogManager.GetLogger(typeof(MainPage));

    public MainPage()
    {
        // Make doubly sure...
        ShowsNavigationUI = false;

        InitializeComponent();

        App.Kernel.Rebind<IUIService>().ToConstant(this);

        MainModel = App.Kernel.Get<MainModel>();
        WindowTitle = MainModel.Title;

        ContentFrame.Navigating += Navigating;
        ContentFrame.Navigated += Navigated;
        ContentFrame.NavigationFailed += NavigationFailed;
    }

    private void Navigating(object sender, NavigatingCancelEventArgs args)
    {
        object dataContext = null;
        if(ContentFrame.Content is FrameworkElement) {
            dataContext = ((FrameworkElement)ContentFrame.Content).DataContext;
        } else if(ContentFrame.Content is FrameworkContentElement) {
            dataContext = ((FrameworkContentElement)ContentFrame.Content).DataContext;
        }

        if(dataContext is ISaveable && ((ISaveable)dataContext).NeedsSave) {
            if(MessageControl.UnsavedSync() != MessageControl.Button.Yes) {
                args.Cancel = true;
            }
        }
    }

    private void Navigated(object sender, NavigationEventArgs e)
    {
        var mi = e.ExtraData as MenuItemModel;

        if(mi == null) {
            var page = e.Content as IMenuItemPage;

            if(page != null) {
                mi = page.MenuItem;
            }

            if(mi == null) {
                log.DebugFormat("Navigated to {0} ({1}) without menu item", e.Content, e.Uri);
                return;
            }
        }

        MainModel.CurrentMenuItem = mi;

        if(mi.Type != MenuItemType.Folder) {
            Settings.Default.AddRecentMenuItem(new RecentMenuItem(mi.MenuItem));
        }
    }

    #region Generic Edit command

    private void EditCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.Handled = true;
        e.CanExecute = false;

        var param = Unwrap(e.Parameter);
        var paramType = GetEditType(param);
        if(paramType == null || !editPages.ContainsKey(paramType)) {
            return;
        }

        e.CanExecute = ToConstructorArgument(param) != null;
    }

    private void EditExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Edit(e.Parameter);
    }

    private void Edit(object param)
    {
        var paramType = GetEditType(param);
        if(paramType == null || !editPages.ContainsKey(paramType)) {
            log.WarnFormat("Page for param {0} (type {1}) not found", param, paramType);
            return;
        }

        if(param is IList) {
            var list = (IList)param;
            if(list.Count > 1000) {
                Show("Too many items selected", "Please select no more than 1000 items at a time", messageTheme: MessageTheme.Warning);
                return;
            }
        }

        var arg = ToConstructorArgument(param);
        if(arg == null) {
            log.Warn("Unexpected parameter " + param + " supplied to EditExecuted");
            return;
        }

        var pageType = editPages[paramType];

        try {
            log.DebugFormat("Got a parameter of type {0}, navigating to edit page {1}", param.GetType(), pageType);

            Navigate(MakePage(pageType, arg));
        } catch(Exception ex) {
            log.Error("Unable to load edit page for parameter " + param, ex);
        }
    }


    private static Page MakePage(Type pageType, params IParameter[] p)
    {
        var page = (Page)App.Kernel.Get(pageType, p);
        var dp = ClientUtil.GetViewModelProperty(page.GetType());
        if(dp != null) {
            page.Loaded += (o, args) => {
                var skrap = App.Kernel.Get(dp.PropertyType, p);
                page.SetValue(dp, App.Kernel.Get(dp.PropertyType, p));
            };
            page.Unloaded += (o, args) => {
                try {
                    page.ClearValue(dp);
                } catch(Exception e) {
                    // Often happens when datagrid is in edit mode when navigating away from page:
                    // http://connect.microsoft.com/VisualStudio/feedback/details/571967/wpf-datagrid-causes-crash-with-sorting-is-not-allowed-during-an-addnew-or-edititem-transaction
                    log.Warn("Error while unloading page", e);
                }
            };

            ViewModelBehavior.SetUpdateUIError(page, true);
        }

        return page;
    }

    #endregion

    #region Navigate command

    private void NavigateCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = e.Parameter is Type;
        e.Handled = true;
    }

    private void NavigateExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        var type = e.Parameter as Type;
        if(type == null) {
            return;
        }

        Navigate(MakePage(type));
        e.Handled = true;
    }

    #endregion

    #region IUIService implementation 

    public void Navigate(Type type, params Tuple<string, object>[] parameters)
    {
        Navigate(MakePage(type, parameters.Select(x => new ConstructorArgument(x.Item1, x.Item2)).ToArray()));
    }

    public void Navigate(Type type, MenuItemModel menuItem, params Tuple<string, object>[] parameters)
    {
        Navigate(MakePage(type, parameters.Select(x => new ConstructorArgument(x.Item1, x.Item2))
            .Prepend(new ConstructorArgument("menuItem", menuItem))
            .Prepend(new ConstructorArgument("props", menuItem.Params))
            .ToArray()), 
            menuItem);
    }

    public void Navigate(Page content, object extraData = null)
    {
        if(ContentFrame != null) {
            if(ContentFrame.Content is DependencyObject) {
                foreach(var dg in WpfUtil.FindDescendants<DataGrid>((DependencyObject)ContentFrame.Content)) {
                    while(!dg.CommitEdit()) { /* Keep committing */ }
                }
            }

            ContentFrame.Navigate(content, extraData);
        }
    }

    public bool NavigateBack()
    {
        if(ContentFrame != null && ContentFrame.CanGoBack) {
            ContentFrame.GoBack();
            return true;
        } 

        if(NavigationService != null && NavigationService.CanGoBack) {
            NavigationService.GoBack();
            return true;
        }

        return false;
    }

}

さらに詳しい情報が必要な場合は教えてください。

4

0 に答える 0