C# MVVM设置默认值

C# MVVM设置默认值,c#,wpf,mvvm,C#,Wpf,Mvvm,我确信这是一个非常常见的场景,我想知道MVVM开发人员是如何解决这个问题的 我有一个按需实例化的ViewModel,它会一直持续到用户显式删除它为止。它的相应视图会根据需要加载到UI上。视图可以卸载,其ViewModel可能仍存在于应用程序中 在我的场景中,我在视图中有一个预设颜色的列表框(通过将其ItemsSource设置为SolidColorBrush的Xaml定义的ObservableCollection) 我将ListBox的SelectedItem属性绑定到ViewModel中的一个属

我确信这是一个非常常见的场景,我想知道MVVM开发人员是如何解决这个问题的

我有一个按需实例化的ViewModel,它会一直持续到用户显式删除它为止。它的相应视图会根据需要加载到UI上。视图可以卸载,其ViewModel可能仍存在于应用程序中

在我的场景中,我在视图中有一个预设颜色的列表框(通过将其ItemsSource设置为SolidColorBrush的Xaml定义的ObservableCollection)

我将ListBox的SelectedItem属性绑定到ViewModel中的一个属性,这样当再次加载视图时,SelectedItem会正确显示ListBox中最后一个选中的项目,并且当用户选择不同的颜色时,VM会处理更改


我的问题是,当第一次加载视图时,如何将默认值(例如SolidColorBrush的ObservableCollection中的第三项)设置为ViewModel?

通常在MVVM中,SolidBrushColor的ObservableCollection应定义为ViewModal中的属性。并且该属性应该绑定到您的ListBox。现在,要设置默认值,可以在ViewModal的构造函数中设置它

如果绑定到SelectedItem的属性声明为dependency属性,则可以将dependency属性的默认值设置为所需的任何值

 public static readonly DependencyProperty SelectedColorProperty
   = DependencyProperty.Register("SelectedColor", typeof(SolidBrushColor ), 
                                                typeof(<yourviewmodel>),
                                                new UIPropertyMetadata(GetDefaultColor()));

  Where GetDefaultColor() is a static method in your ViewModel, 
  which will return the required color from your ObservableCollection .
public static readonly dependencProperty SelectedColorProperty
=DependencyProperty.寄存器(“SelectedColor”,typeof(SolidBrushColor),
typeof(),
新的UIPropertyMetadata(GetDefaultColor());
其中GetDefaultColor()是ViewModel中的静态方法,
这将从ObservableCollection返回所需的颜色。

我相信您的实现中存在错误。拥有MVVM的原因是“关注点分离”。这使得您的视图只是一个实现,在需要时可以切换或更新。一旦您开始将属于应用程序逻辑一部分的内容放入视图中,您就陷入了维护难题,然后意大利面代码就会很快出现

有些人说,“不要在你的视图中放置任何代码”,我99%的时间都同意。我说“不要将任何域/应用程序/业务逻辑放在您的视图中。”

每当你试图在视图中添加一些代码时,问问自己“如果我从WPF切换到另一个框架,我的应用程序还能工作吗?”如果答案是否定的,那么修改你的视图模型,将你试图在视图中添加的内容纳入其中。

首先阅读答案如果你对他的问题的回答将是“是””试试这个

XAML 总结 您可以看到默认的
SelectedItem
SelectedIndex
设置,该索引按
OneTime
模式绑定到
mySelectedIndex
。我还将在这里展示如何将其导入视图

我知道这将如何帮助某人。

通常我在构造函数中设置默认值,除非加载默认值可能需要一些时间,在这种情况下,我将在绑定属性的getter中设置call方法来设置默认值

这样做的原因是为了简化维护。如果我正在查找设置默认值的位置,以便查看或更改它,那么首先检查的是构造函数。它比滚动属性更容易找到,并且已知包含初始化逻辑

MyViewModel()
{
    // Set defaults 
    SelectedColor = Brushes.Red;
}
对于可能需要更长时间加载的属性,我使用了一个在getter中调用的方法,原因与此相同。通常,我的所有属性及其getter/setter都隐藏在一个区域中,我发现在我的类中找到名为
LoadColors()
的方法要比在我拥有的大量属性列表中找到
Colors
属性容易得多。而且,它是可重用的,因此如果我需要重置值之类的操作,无需重复代码即可轻松完成

ObservableCollection<SolidColorBrush> Colors
{
    get
    {
        if (_colors == null)
            LoadColors();

        return _colors;
    }
    set { ... }
}

void LoadColors()
{
    // Initialization logic here
}
最后但并非最不重要的一点是,您始终可以使用视图背后的代码来执行视图特定的逻辑,就像您的示例一样。比如说,

void ComboBox_Loaded(object obj, EventArgs e)
{
    if (MyComboBox.SelectedIndex == -1)
        MyComboBox.SelectedIndex = 2;
}

实际上我使用的是MVVM light,因此我没有使用DependencyProperty,而是使用INotifyPropertyChange接口。也就是说,我明白你的意思,但这里的场景是我的ObservableCollection是在视图级别而不是在ViewModel中定义的,因为这是一个颜色集合,设计师可以修改他一侧的预设颜色,也可以设置他一侧的默认颜色。将默认值作为参数传递给视图模型构造函数2。在xaml中使用Converter和ConverterParameter,将ListBox SelectedItem绑定到ViewModel属性。正如我在与akapoor的回复中所解释的,我的ObservableCollection是在视图级别定义的,而不是ViewModel级别,这就是为什么我想知道你们将如何解决这个问题?嗨,谢谢你们的建议。我无意将业务逻辑置于我的观点中。我不知道你在哪里读到我的评论,我把代码放在我的观点。。。隐马尔可夫模型?我还坚信“关注点分离”政策。。。在我的MVVM实现中,我的ViewModel搜索它对应的视图,我的视图没有创建它的ViewModel的命令。这就是为什么我提到我的视图可能会被破坏,但它的ViewModel仍然保留在内存中。当用户再次请求它的视图时,视图将填充ViewModel上的最后一组属性。FallbackValue为+1,并建议我,如果绑定被破坏,它不仅有效
MyViewModel()
{
    // Set defaults 
    SelectedColor = Brushes.Red;
}
ObservableCollection<SolidColorBrush> Colors
{
    get
    {
        if (_colors == null)
            LoadColors();

        return _colors;
    }
    set { ... }
}

void LoadColors()
{
    // Initialization logic here
}
<!-- You may have to look up the exact syntax for Brushes.Red -->
<ListBox SelectedItem="{Binding SelectedColor, FallbackValue=Red}" />
void ComboBox_Loaded(object obj, EventArgs e)
{
    if (MyComboBox.SelectedIndex == -1)
        MyComboBox.SelectedIndex = 2;
}