Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF/MVVM抽象通用方法_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# WPF/MVVM抽象通用方法

C# WPF/MVVM抽象通用方法,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,所以,社区,请容忍我,因为我是一个新手,我仍然在慢慢地学习。我试图在网上实现所有可能的解决方案,但没有成功。我想我完全把自己和DependencyMethods、DependencyProperties、RelayCommand、ICommand、BaseViewModels等混淆了 这是我的场景。。。我有一个MainWindowMainWindow,它有一个包含UserControlSampleUC的框架。MainWindow和UserControl数据上下文指向各自的ViewModelsMa

所以,社区,请容忍我,因为我是一个新手,我仍然在慢慢地学习。我试图在网上实现所有可能的解决方案,但没有成功。我想我完全把自己和DependencyMethods、DependencyProperties、RelayCommand、ICommand、BaseViewModels等混淆了

这是我的场景。。。我有一个MainWindowMainWindow,它有一个包含UserControlSampleUC的框架。MainWindow和UserControl数据上下文指向各自的ViewModelsMainWindowVM、SampleUCVM。MainWindowVM和SampleUCVM是基础ViewModelBASEVM的子级,该基础ViewModelBASEVM使用通过ObservableCollection帮助程序类更改的InotifyProperty。SampleUC中有一个组合框,用于保存SampleUCVM中使用fillFacility方法构造的Facility ObservableCollection,并在组合框中使用GetFacilityNum方法选择时存储SelectedFacilityNum

我想从SampleUCVM中取出fillFacility和GetFacilityNum方法,并将它们放在BASEVM或一个单独的类中,其他ViewModels可以在其中访问和使用它们。它们将在我的整个项目中反复使用。有人能告诉我怎么做吗?谢谢你的帮助和耐心

SampleUC.xaml


你让事情变得比实际情况复杂得多。 ObservableCollection足以通知WPF控制部门到目前为止发生的变更;只需确保它是从XAML正确绑定的

因此

公共收集设施 { 获取{return\u facilitiesList;} 设置 { SetPropertyref_设施列表,值=>设施; } }

是多余的,应简化为

公共收集设施 { 收到 }

并且只初始化一次-从构造函数开始

只要您希望它位于基本视图模型,就可以将代码移到那里。然后从基础模型继承您的子模型,这样子模型将获得这样一个属性作为其自身的一部分

忘记设置值。。。除非您注册自己的自定义DependencyProperty,否则该属性仅适用于高级方案

这些都是起点

玩得开心。

我同意彼得·杜尼霍的观点。你的问题太宽泛了,没有明确的答案,但我想向你强调几点。 BASEVM的用途是什么?为什么它继承自ObserveObject

类包装对象,以便其他类可以通知 改变事件。通常,此类被设置为依赖项属性 并允许其他类观察任何更改 在价值观上

如果您想要一个基本的通知更改功能,您可以这样做

public class ViewModelBase:INotifyPropertyChanged{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }
    protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
    {
        PropertyChanged?.Invoke(this, args);
    }
    protected void RaisePropertyChanged([CallerMemberName]string propertyName = null)
    {
        OnPropertyChanged(propertyName);
    }
    protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Equals(storage, value)) return false;

        storage = value;
        RaisePropertyChanged(propertyName);

        return true;
    }
}
我想退出工厂,然后 从SampleUCVM获取FacilityNum并将其放置在 BASEVM或一个单独的类,用户可以在其中访问和使用它们 其他视图模型

fillFacility方法,如代码中所示,正在处理数据库。据我所知,在MVVM模式中,视图模型意味着在视图和模型之间沉思

视图模型充当视图和模型之间的中介, 并负责处理视图逻辑。通常,视图 模型通过调用模型中的方法与模型交互 上课。然后,视图模型以表单形式提供来自模型的数据 视图可以很容易地使用。视图模型从数据库中检索数据 模型,然后使数据可用于视图,并可以重新格式化 以某种方式处理数据,使视图更易于处理


因此,我建议将数据访问逻辑从视图模型分离到单独的数据访问层。例如,您可以使用Repository模式并创建FacilityRepository。然后,您可以向需要此功能的ViewModels提供此存储库。如果您想更严格,可以创建IFacilityRepository接口,让FacilityRepository实现它,然后将此接口注入任何需要此功能的ViewModel。

我将考虑为此类功能实现数据访问层。例如:

public class DataAccess
{
    public ObservableCollection<Facilities> GetFacilities()
    {
        ObservableCollection<Facilities> facilities = new ObservableCollection<Facilities>();

        using (MySqlConnection con = new MySqlConnection(dbConnectionString))
        {
            con.Open();
            string Query = "SELECT * FROM facilities";
            MySqlCommand createCommand = new MySqlCommand(Query, con);
            MySqlDataReader dr = createCommand.ExecuteReader();
            int count = 1;
            while (dr.Read())
            {
                string FacilityName = dr.GetString(1);
                facilities facilityname = new Facilities(count, FacilityName);
                facilities.Add(facilityname);
                count++;
            }
            con.Close();
        }

        return facilities;
    }
}
然后,您可以在ViewModel类或某些ViewModel基类中包含该类的实例


关于GetFacilityNum方法,这也可以进入DataAccess类,但我个人认为更好的解决方案是尽可能将Facility_ID_Num作为Facility类的属性。然后,您只需修改GetFacilities方法即可将其引入,但在应用程序中,您始终可以访问该方法,而无需任何数据库调用,因为它是您的设施模型的一部分。

您的问题太广泛,有许多可能的答案。也就是说,虚拟机应该非常简单, 尤其是程序本身变得更加复杂。在视图模型之间共享与设施相关的代码是否有用还不清楚,但根据您在此处发布的内容,似乎更可能所有代码都属于一个完全不同的类。然后,任何需要该功能的视图模型类都可以具有该不同类的实例,而不是具有该功能的类的实例。
    public class BASEVM : ObservableObject
{
    public BASEVM()
    {

    }
}
public class ViewModelBase:INotifyPropertyChanged{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }
    protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
    {
        PropertyChanged?.Invoke(this, args);
    }
    protected void RaisePropertyChanged([CallerMemberName]string propertyName = null)
    {
        OnPropertyChanged(propertyName);
    }
    protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Equals(storage, value)) return false;

        storage = value;
        RaisePropertyChanged(propertyName);

        return true;
    }
}
public int SelectedFacilityNum
{
    get { return _selectedFacilityNum; }
    set { SetProperty(ref _selectedFacilityNum,value); }
}
public class DataAccess
{
    public ObservableCollection<Facilities> GetFacilities()
    {
        ObservableCollection<Facilities> facilities = new ObservableCollection<Facilities>();

        using (MySqlConnection con = new MySqlConnection(dbConnectionString))
        {
            con.Open();
            string Query = "SELECT * FROM facilities";
            MySqlCommand createCommand = new MySqlCommand(Query, con);
            MySqlDataReader dr = createCommand.ExecuteReader();
            int count = 1;
            while (dr.Read())
            {
                string FacilityName = dr.GetString(1);
                facilities facilityname = new Facilities(count, FacilityName);
                facilities.Add(facilityname);
                count++;
            }
            con.Close();
        }

        return facilities;
    }
}