C# 以下代码使用MVVM而不是主窗口

C# 以下代码使用MVVM而不是主窗口,c#,wpf,xaml,mvvm,listbox,C#,Wpf,Xaml,Mvvm,Listbox,我使用的是从主窗口复制粘贴的以下代码,该窗口按预期工作 <TextBox x:Name="name1" AcceptsReturn="True" AllowDrop="True" PreviewDragEnter="DropText_PreviewDragEnter" PreviewDrop="DropText_PreviewDrop"

我使用的是从主窗口复制粘贴的以下代码,该窗口按预期工作

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
  • 我已经创建了视图,它是用户控件,并将 来自主窗口XAML的代码
  • 在视图模型中,我放置了用户模型的引用
  • 在用户控件中,我从主窗口中输入 与事件处理程序相关,例如 DropText\u预览输入和列表框\u选择已更改
目前我有2个问题,在用户控制,我不知道如何克服

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
1。列表框出现的所有用户控件中的错误(例如,来自ListBox\u SelectionChanged System.Windows.Controls.ListBox.SelectedItems.Count>0。所选项目标记为红色,并显示以下错误

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
“无法在静态上下文中访问非静态属性SelectedItems项源”。,不确定原因是什么,因为在主窗口中它与静态相同

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
2.由于我从主窗口复制了代码,因此用户控件中存在对用户对象的引用,我认为这在MVVM中是不可接受的,我应该如何更改它?例如

var mySelectedItem = System.Windows.Controls.ListBox.SelectedItem as User;
    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
这是代码。

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
我将感谢你的帮助

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
视图模型

public partial class ModelView : UserControl
{
    private const string DRAG_SOURCE = "DragSource";

    public ModelView()
    {
        InitializeComponent();
        DataContext = new ModelView();
    }



    //Drag Over from text box to List box


    private void ListBox_PreviewDrop(object sender, DragEventArgs e)
    {
        object dragSource = e.Data.GetData(DRAG_SOURCE);
        if (dragSource != null && dragSource is TextBox)
        {
            (dragSource as TextBox).Text = String.Empty;
        }
        if (!String.IsNullOrEmpty(e.Data.GetData(DataFormats.StringFormat).ToString()) && dragSource is TextBox)
        {
            _UsersList.Add(new User {Name = e.Data.GetData(DataFormats.StringFormat).ToString()});
        }
        else
        {
            e.Handled = true;
        }
    }

    }
}
    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
Xaml是

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
模型视图

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
internal class ModelView
{
    private ObservableCollection<User> _UsersList = new ObservableCollection<User>();

    public ObservableCollection<User> UserList
    {
        get { return _UsersList; }
    }

    public void InitUsers()
    {
        _UsersList.Add(new User {Name = "fff"});

        //Sort the User collection
        ICollectionView usersView = CollectionViewSource.GetDefaultView(_UsersList);
        usersView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));

    }

}
内部类模型视图
{
private ObservableCollection_UsersList=new ObservableCollection();
公共ObservableCollection用户列表
{
获取{return\u UsersList;}
}
公共用户()
{
_添加(新用户{Name=“fff”});
//对用户集合进行排序
ICollectionView usersView=CollectionViewSource.GetDefaultView(\u UsersList);
usersView.SortDescriptions.Add(新的SortDescription(“Name”,ListSortDirection.升序));
}
}

您必须通过

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
yourListBoxName.SelectedItems.Count > 0
您无法通过访问它

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
System.Windows.Controls.ListBox.SelectedItems.Count
同样适用于

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
var mySelectedItem = System.Windows.Controls.ListBox.SelectedItem as User;
请使用以下命令

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
var mySelectedItem = yourListBoxName.SelectedItem as User;

您必须通过以下方式访问列表框:

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
yourListBoxName.SelectedItems.Count > 0
您无法通过访问它

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
System.Windows.Controls.ListBox.SelectedItems.Count
同样适用于

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
var mySelectedItem = System.Windows.Controls.ListBox.SelectedItem as User;
请使用以下命令

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
var mySelectedItem = yourListBoxName.SelectedItem as User;

您已经有两个答案解释了为什么第一个问题发生在中。以下几点是@Will在评论中说的MVVM实现混乱的地方,我可以在您的代码中看到:

    <TextBox x:Name="name1"  
              AcceptsReturn="True"
              AllowDrop="True" 
              PreviewDragEnter="DropText_PreviewDragEnter"
              PreviewDrop="DropText_PreviewDrop"
              PreviewMouseDown="DropText_PreviewMouseDown"
              HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
              VerticalAlignment="Top" Width="70"/>
  • 模型视图中的
    用户列表
    是一个模型,与模型视图模型一样
  • 而模型视图本身就是一个视图模型,与模型视图-视图模型
  • 那么你所谓的视图模型实际上是一个视图,在模型-视图-视图--ViewModel视图中。它继承了
    用户控制
    ,而
    用户控制
    是一个视图,与
    窗口
    页面
    等没有区别。它们都是视图。即使我们同意称它为视图模型,它也违反了MVVM原则无处不在,因为视图模型不应该引用视图/UI控件对象

  • 不是直接回答你的问题,但我希望你对MVVM模式有一个更好的了解。

    你已经有两个答案解释了第一个问题发生的原因。下面几点是@Will在评论中说的MVVM实现一团糟,我可以在你的代码中看到:

        <TextBox x:Name="name1"  
                  AcceptsReturn="True"
                  AllowDrop="True" 
                  PreviewDragEnter="DropText_PreviewDragEnter"
                  PreviewDrop="DropText_PreviewDrop"
                  PreviewMouseDown="DropText_PreviewMouseDown"
                  HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
                  VerticalAlignment="Top" Width="70"/>
    
  • 模型视图中的
    用户列表
    是一个模型,与模型视图模型一样
  • 而模型视图本身就是一个视图模型,与模型视图-视图模型
  • 那么你所谓的视图模型实际上是一个视图,在模型-视图-视图--ViewModel视图中。它继承了
    用户控制
    ,而
    用户控制
    是一个视图,与
    窗口
    页面
    等没有区别。它们都是视图。即使我们同意称它为视图模型,它也违反了MVVM原则无处不在,因为视图模型不应该引用视图/UI控件对象

  • 不是直接回答您的问题,但我希望您对MVVM模式有更好的了解。

    @phil正确地指出,您不能像这样访问
    列表框:

        <TextBox x:Name="name1"  
                  AcceptsReturn="True"
                  AllowDrop="True" 
                  PreviewDragEnter="DropText_PreviewDragEnter"
                  PreviewDrop="DropText_PreviewDrop"
                  PreviewMouseDown="DropText_PreviewMouseDown"
                  HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
                  VerticalAlignment="Top" Width="70"/>
    
    System.Windows.Controls.ListBox
    
    string selectedItemName = SelectedItem.Name;
    
    他没有提到的是,如果你在使用MVVM,你根本不应该访问
    列表框
    。很明显,你现在没有使用MVVM,但如果你想,我建议你仔细阅读它,这样你就可以从中获得全部好处。拥有视图和视图模型并不意味着你在使用MVVM

        <TextBox x:Name="name1"  
                  AcceptsReturn="True"
                  AllowDrop="True" 
                  PreviewDragEnter="DropText_PreviewDragEnter"
                  PreviewDrop="DropText_PreviewDrop"
                  PreviewMouseDown="DropText_PreviewMouseDown"
                  HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
                  VerticalAlignment="Top" Width="70"/>
    
    在MVVM中,我们操作数据,而不是UI控件。因此,您需要在视图模型中创建一个
    SelectedItem
    属性,并将其绑定到
    列表框。SelectedItem
    属性,然后您将始终有权访问所选项目:

        <TextBox x:Name="name1"  
                  AcceptsReturn="True"
                  AllowDrop="True" 
                  PreviewDragEnter="DropText_PreviewDragEnter"
                  PreviewDrop="DropText_PreviewDrop"
                  PreviewMouseDown="DropText_PreviewMouseDown"
                  HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
                  VerticalAlignment="Top" Width="70"/>
    
    public User SelectedItem { get; set; } // Implement INotifyPropertyChanged here
    
    ...
    
    <ListBox ItemsSource="{Binding YourCollection}" SelectedItem="{Binding SelectedItem}"/>
    

    @phil正确地指出,您不能像这样访问
    列表框

        <TextBox x:Name="name1"  
                  AcceptsReturn="True"
                  AllowDrop="True" 
                  PreviewDragEnter="DropText_PreviewDragEnter"
                  PreviewDrop="DropText_PreviewDrop"
                  PreviewMouseDown="DropText_PreviewMouseDown"
                  HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
                  VerticalAlignment="Top" Width="70"/>
    
    System.Windows.Controls.ListBox
    
    string selectedItemName = SelectedItem.Name;
    
    他没有提到的是,如果你在使用MVVM,你根本不应该访问
    列表框
    。很明显,你现在没有使用MVVM,但如果你想,我建议你仔细阅读它,这样你就可以从中获得全部好处。拥有视图和视图模型并不意味着你在使用MVVM

        <TextBox x:Name="name1"  
                  AcceptsReturn="True"
                  AllowDrop="True" 
                  PreviewDragEnter="DropText_PreviewDragEnter"
                  PreviewDrop="DropText_PreviewDrop"
                  PreviewMouseDown="DropText_PreviewMouseDown"
                  HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
                  VerticalAlignment="Top" Width="70"/>
    
    在MVVM中,我们操作数据,而不是UI控件。因此,您需要在视图模型中创建一个
    SelectedItem
    属性,并将其绑定到
    列表框。SelectedItem
    属性,然后您将始终有权访问所选项目:

        <TextBox x:Name="name1"  
                  AcceptsReturn="True"
                  AllowDrop="True" 
                  PreviewDragEnter="DropText_PreviewDragEnter"
                  PreviewDrop="DropText_PreviewDrop"
                  PreviewMouseDown="DropText_PreviewMouseDown"
                  HorizontalAlignment="Left" Height="20" Margin="360,70,0,0" TextWrapping="Wrap" Text="" 
                  VerticalAlignment="Top" Width="70"/>
    
    public User SelectedItem { get; set; } // Implement INotifyPropertyChanged here
    
    ...
    
    <ListBox ItemsSource="{Binding YourCollection}" SelectedItem="{Binding SelectedItem}"/>
    

    由于Im使用拖放(请参见文本框xaml)我需要将DropText\u PreviewDragEnter等事件的代码放在用户控件中,否则我会出错!!!,如果你不想破坏mvvm,你会怎么做,请提供示例任何事件都可以通过将其包装在附加属性中以mvvm的方式处理…这是一个简单的例子。在@Sheridan这里,我不能同意你的观点。
    Model
    s和