GithubHelp home page GithubHelp logo

Comments (5)

joshman1019 avatar joshman1019 commented on July 2, 2024

I think a bit more information may be needed in order to answer your question. There is not enough code posted to determine the control flow of your app up to this point. Typically, if passing a base page or something similar into a ViewModel I would use an interface. But that's just what I can gather from what is posted. I will be glad to help if you can give a bit more context.

from fasetto-word.

BEDIRHANSAMSA avatar BEDIRHANSAMSA commented on July 2, 2024

Hi, thanks for your answer.

I have a Product List page and I want to which in the list double-clicked product id send product details page but I can't send it product id to product detail view model. How can I send Product Id another view model?

I tried field-initialization but not work because if the class has a constructor, first initializing constructor and after sets fields. Example:
image
image

I tried ProductDetail constructor parameter but I got an error;
'ProductDetailViewModel' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TVm' in the generic type or method 'BasePage<TVm>'

Sorry for my bad English.

I'm using BasePage and BaseViewModel.

using Dna;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace Fasetto.Word
{
/// <summary>
/// The base page for all pages to gain base functionality
/// </summary>
public class BasePage : UserControl
{
#region Private Member
/// <summary>
/// The View Model associated with this page
/// </summary>
private object mViewModel;
#endregion
#region Public Properties
/// <summary>
/// The animation the play when the page is first loaded
/// </summary>
public PageAnimation PageLoadAnimation { get; set; } = PageAnimation.SlideAndFadeInFromRight;
/// <summary>
/// The animation the play when the page is unloaded
/// </summary>
public PageAnimation PageUnloadAnimation { get; set; } = PageAnimation.SlideAndFadeOutToLeft;
/// <summary>
/// The time any slide animation takes to complete
/// </summary>
public float SlideSeconds { get; set; } = 0.4f;
/// <summary>
/// A flag to indicate if this page should animate out on load.
/// Useful for when we are moving the page to another frame
/// </summary>
public bool ShouldAnimateOut { get; set; }
/// <summary>
/// The View Model associated with this page
/// </summary>
public object ViewModelObject
{
get => mViewModel;
set
{
// If nothing has changed, return
if (mViewModel == value)
return;
// Update the value
mViewModel = value;
// Fire the view model changed method
OnViewModelChanged();
// Set the data context for this page
DataContext = mViewModel;
}
}
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
public BasePage()
{
// Don't bother animating in design time
if (DesignerProperties.GetIsInDesignMode(this))
return;
// If we are animating in, hide to begin with
if (PageLoadAnimation != PageAnimation.None)
Visibility = Visibility.Collapsed;
// Listen out for the page loading
Loaded += BasePage_LoadedAsync;
}
#endregion
#region Animation Load / Unload
/// <summary>
/// Once the page is loaded, perform any required animation
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void BasePage_LoadedAsync(object sender, System.Windows.RoutedEventArgs e)
{
// If we are setup to animate out on load
if (ShouldAnimateOut)
// Animate out the page
await AnimateOutAsync();
// Otherwise...
else
// Animate the page in
await AnimateInAsync();
}
/// <summary>
/// Animates the page in
/// </summary>
/// <returns></returns>
public async Task AnimateInAsync()
{
// Make sure we have something to do
if (PageLoadAnimation == PageAnimation.None)
return;
switch (PageLoadAnimation)
{
case PageAnimation.SlideAndFadeInFromRight:
// Start the animation
await this.SlideAndFadeInAsync(AnimationSlideInDirection.Right, false, SlideSeconds, size: (int)Application.Current.MainWindow.Width);
break;
}
}
/// <summary>
/// Animates the page out
/// </summary>
/// <returns></returns>
public async Task AnimateOutAsync()
{
// Make sure we have something to do
if (PageUnloadAnimation == PageAnimation.None)
return;
switch (PageUnloadAnimation)
{
case PageAnimation.SlideAndFadeOutToLeft:
// Start the animation
await this.SlideAndFadeOutAsync(AnimationSlideInDirection.Left, SlideSeconds);
break;
}
}
#endregion
/// <summary>
/// Fired when the view model changes
/// </summary>
protected virtual void OnViewModelChanged()
{
}
}
/// <summary>
/// A base page with added ViewModel support
/// </summary>
public class BasePage<VM> : BasePage
where VM : BaseViewModel, new()
{
#region Public Properties
/// <summary>
/// The view model associated with this page
/// </summary>
public VM ViewModel
{
get => (VM)ViewModelObject;
set => ViewModelObject = value;
}
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
public BasePage() : base()
{
// If in design time mode...
if (DesignerProperties.GetIsInDesignMode(this))
// Just use a new instance of the VM
ViewModel = new VM();
else
// Create a default view model
ViewModel = Framework.Service<VM>() ?? new VM();
}
/// <summary>
/// Constructor with specific view model
/// </summary>
/// <param name="specificViewModel">The specific view model to use, if any</param>
public BasePage(VM specificViewModel = null) : base()
{
// Set specific view model
if (specificViewModel != null)
ViewModel = specificViewModel;
else
{
// If in design time mode...
if (DesignerProperties.GetIsInDesignMode(this))
// Just use a new instance of the VM
ViewModel = new VM();
else
{
// Create a default view model
ViewModel = Framework.Service<VM>() ?? new VM();
}
}
}
#endregion
}
}

using Fasetto.Word.Core;
using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace Fasetto.Word
{
/// <summary>
/// A base view model that fires Property Changed events as needed
/// </summary>
public class BaseViewModel : INotifyPropertyChanged
{
#region Protected Members
/// <summary>
/// A global lock for property checks so prevent locking on different instances of expressions.
/// Considering how fast this check will always be it isn't an issue to globally lock all callers.
/// </summary>
protected object mPropertyValueCheckLock = new object();
#endregion
/// <summary>
/// The event that is fired when any child property changes its value
/// </summary>
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
/// <summary>
/// Call this to fire a <see cref="PropertyChanged"/> event
/// </summary>
/// <param name="name"></param>
public void OnPropertyChanged(string name)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#region Command Helpers
/// <summary>
/// Runs a command if the updating flag is not set.
/// If the flag is true (indicating the function is already running) then the action is not run.
/// If the flag is false (indicating no running function) then the action is run.
/// Once the action is finished if it was run, then the flag is reset to false
/// </summary>
/// <param name="updatingFlag">The boolean property flag defining if the command is already running</param>
/// <param name="action">The action to run if the command is not already running</param>
/// <returns></returns>
protected async Task RunCommandAsync(Expression<Func<bool>> updatingFlag, Func<Task> action)
{
// Lock to ensure single access to check
lock (mPropertyValueCheckLock)
{
// Check if the flag property is true (meaning the function is already running)
if (updatingFlag.GetPropertyValue())
return;
// Set the property flag to true to indicate we are running
updatingFlag.SetPropertyValue(true);
}
try
{
// Run the passed in action
await action();
}
finally
{
// Set the property flag back to false now it's finished
updatingFlag.SetPropertyValue(false);
}
}
/// <summary>
/// Runs a command if the updating flag is not set.
/// If the flag is true (indicating the function is already running) then the action is not run.
/// If the flag is false (indicating no running function) then the action is run.
/// Once the action is finished if it was run, then the flag is reset to false
/// </summary>
/// <param name="updatingFlag">The boolean property flag defining if the command is already running</param>
/// <param name="action">The action to run if the command is not already running</param>
/// <typeparam name="T">The type the action returns</typeparam>
/// <returns></returns>
protected async Task<T> RunCommandAsync<T>(Expression<Func<bool>> updatingFlag, Func<Task<T>> action, T defaultValue = default(T))
{
// Lock to ensure single access to check
lock (mPropertyValueCheckLock)
{
// Check if the flag property is true (meaning the function is already running)
if (updatingFlag.GetPropertyValue())
return defaultValue;
// Set the property flag to true to indicate we are running
updatingFlag.SetPropertyValue(true);
}
try
{
// Run the passed in action
return await action();
}
finally
{
// Set the property flag back to false now it's finished
updatingFlag.SetPropertyValue(false);
}
}
#endregion
}
}

Product List:
image

from fasetto-word.

joshman1019 avatar joshman1019 commented on July 2, 2024

I have personally used some sort of state storage for issues like this. I use the MVVM pattern for all of my WPF applications and this is always an issue when loading a new page that is dependent on the data obtained from another.

So your product list page's viewmodel would store the ID in the state manager, and when loaded, the product detail page would retrieve the ID from the state manager. That decouples the two pages from one another.

You could store this state in a database, in a static StateManager class, or some other solution that you feel is best for your application. I'm not sure what methods other MVVM developers use but this has always been the best for my use case. Other methods that I've seen are overly complicated, add way too many steps, and are difficult to maintain and debug.

Without seeing the entire code base I cannot make a solid recommendation, but hopefully this will get you started.

from fasetto-word.

joshman1019 avatar joshman1019 commented on July 2, 2024

Honestly, I tried to use a similar pattern to create a WPF application in the past and had some issues like this.

I never load pages by passing view models. I always allow a page to load a new view model in their constructor and retrieve the data from some sort of state storage that will work for your application.

Again, it is hard to determine without seeing the entire code base, but you might try something similar to avoid these issues.

from fasetto-word.

BEDIRHANSAMSA avatar BEDIRHANSAMSA commented on July 2, 2024

Hi, thanks for your answer and the interest you have shown. I think I found a solution. I changed my Base Page to BasePage in Xaml File and constructor like this;

#region Constructor

/// <summary>
/// Default constructor
/// </summary>
public ProductDetail(Product product)
{
    InitializeComponent();
    ViewModelObject = new ProductDetailViewModel(product);
}

#endregion

In This way I can define fields viewmodel constructor.

#region Constructor

/// <summary>
/// Default constructor
/// </summary>
public ProductDetailViewModel(Product product)
{
    // Set product
    Product = product;
}

#endregion

from fasetto-word.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.