【问题标题】:Difference in xaml terms used for binding用于绑定的 xaml 术语的差异
【发布时间】:2014-08-31 15:06:00
【问题描述】:

我是使用 Silverlight 的 xaml(用于 MVVM 方法)的初学者。我阅读了几份文件,对此感到有些困惑。如果有人能解释以下之间的区别,我将不胜感激。

假设我的 XAML 是:

  xmlns:viewmodel="clr-namespace:smallMVVM"
  ......
  ......  
 <UserControl.Resources>
        <viewmodel:ViewModel x:Key="ViewModel"/>
        <viewmodel:DatetimeToDateConverter x:Key="MyConverter"/>
 </UserControl.Resources>

现在有什么区别:

  1. 如果我这样做 "this.DataContext = new ViewModel();" ,我的意思是在 MainPage.cs 中。如果我执行以下&lt;Grid DataContext="{Binding Source={StaticResource ViewModel}}"&gt;,则在 MainPage.xaml 中。两者有区别吗?

  2. 在某处我看到了 ItemsSource="{StaticResource customers}" 的一些例子。 ItemSourceDataContext 有何不同。而我可以在示例(1) 中看到我在DataContext 的绑定中具有相同的内容(请参阅:Source={StaticResource ViewModel}(2) 它被customers 替换)。两者有何不同?

  3. 有时我也直接看到ItemsSource="{Binding Students}"里面没有StaticResource。它与使用 StaticResource 有何不同?

  4. 有些例子只是Binding="{Binding Name}"

  5. SelectedItemSelectedValue 有何不同?

谁能用一个小而简单的例子解释一下吗?网上搜索有一些典型的例子供初学者理解。

【问题讨论】:

    标签: c# .net silverlight xaml mvvm


    【解决方案1】:

    1) 从技术上讲,数据上下文的两个声明之间没有区别 我喜欢在代码隐藏中进行,如下所示:

    Partial Public Class MainPage
        Inherits UserControl
    
        Private _viewModel As TestViewModel
    
        Public Sub New()
            InitializeComponent()
            _viewModel = TryCast(Resources("TheViewModel"), TestViewModel)
            Me.DataContext = _viewModel
        End Sub
    End Class
    

    2)您不想将 ItemsSource 设置为静态页面资源,而是希望将其设置为 ViewModel 中的属性。下面是一个示例 View 和 ViewModel,注意 VM 上的 Inherits 和 Impelments,它们允许您的 VM 告诉您的 View 属性已更改,并重新加载属性。

    查看:

    <UserControl x:Class="SilverlightTestApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
    xmlns:ModelViewModel="clr-namespace:SilverlightTestApp"  >
    
    <UserControl.Resources>
        <ModelViewModel:TestViewModel x:Key="TheViewModel" />
    </UserControl.Resources>
    
    <Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource TheViewModel}">
        <ItemsControl ItemsSource="{Binding SampleCollection}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"></TextBlock>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
    

    视图模型:

    Imports System.ComponentModel
    Imports System.Collections.ObjectModel
    Public Class TestViewModel
        Inherits DependencyObject
        Implements System.ComponentModel.INotifyPropertyChanged
        Implements INotifyDataErrorInfo
    
        Private _model As TestModel
    
        Sub New()
            Me.New(New TestModel)
        End Sub
    
        Public Sub New(ByVal model As TestModel)
            _model = model
    
            _sampleCollection = New ObservableCollection(Of String)
            _sampleCollection.Add("one")
            _sampleCollection.Add("two")
            _sampleCollection.Add("three")
            _sampleCollection.Add("four")
    
        End Sub
    
        Private _sampleCollection As ObservableCollection(Of String)
        Public Property SampleCollection As ObservableCollection(Of String)
            Get
                Return _sampleCollection
            End Get
            Set(value As ObservableCollection(Of String))             
                If value IsNot Nothing Then
                    _sampleCollection = value
                End If
                Me.OnPropertyChanged("SampleCollection")
    
            End Set
        End Property
    
        Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    
        Protected errors As New Dictionary(Of String, List(Of String))
    
        Protected Sub OnPropertyChanged(ByVal propertyName As String)
            RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))
        End Sub
    
        ' #Region " Validation Plumbing"
        ' Adds the specified error to the errors collection if it is not 
        ' already present, inserting it in the first position if isWarning is 
        ' false. Raises the ErrorsChanged event if the collection changes. 
        Public Sub AddError(ByVal propertyName As String, ByVal [error] As String,
                            ByVal isWarning As Boolean)
    
            If Not errors.ContainsKey(propertyName) Then _
                errors(propertyName) = New List(Of String)()
    
            If Not errors(propertyName).Contains([error]) Then
                If isWarning Then
                    errors(propertyName).Add([error])
                Else
                    errors(propertyName).Insert(0, [error])
                End If
                RaiseErrorsChanged(propertyName)
            End If
    
        End Sub
    
        ' Removes the specified error from the errors collection if it is
        ' present. Raises the ErrorsChanged event if the collection changes.
        Public Sub RemoveError(ByVal propertyName As String, ByVal [error] As String)
    
            If errors.ContainsKey(propertyName) AndAlso
                errors(propertyName).Contains([error]) Then
    
                errors(propertyName).Remove([error])
                If errors(propertyName).Count = 0 Then errors.Remove(propertyName)
                RaiseErrorsChanged(propertyName)
    
            End If
    
        End Sub
        Public Sub RemoveError(ByVal propertyName As String)
    
            If errors.ContainsKey(propertyName) Then
    
                errors.Remove(propertyName)
                RaiseErrorsChanged(propertyName)
    
            End If
    
        End Sub
    
        Public Sub RaiseErrorsChanged(ByVal propertyName As String)
            OnPropertyChanged("HasErrors")
            RaiseEvent ErrorsChanged(Me,
                New DataErrorsChangedEventArgs(propertyName))
        End Sub
    
        Public Event ErrorsChanged As EventHandler(Of DataErrorsChangedEventArgs) _
            Implements INotifyDataErrorInfo.ErrorsChanged
    
        Public Function GetErrors(ByVal propertyName As String) _
            As System.Collections.IEnumerable _
            Implements INotifyDataErrorInfo.GetErrors
    
            If (String.IsNullOrEmpty(propertyName) OrElse
                Not errors.ContainsKey(propertyName)) Then Return Nothing
            Return errors(propertyName)
    
        End Function
    
        Public ReadOnly Property HasErrors As Boolean _
            Implements INotifyDataErrorInfo.HasErrors
            Get
                Return errors.Count > 0
            End Get
        End Property
    
    End Class
    

    上面的关键部分是Me.OnPropertyChanged("SampleCollection"),它告诉视图更新它绑定的属性。

    关于架构的说明,如果您正在构建具有多个 View 和 ViewModel 的应用程序,创建一个 ViewModelBase 并让它继承 DependencyObject 并实现 INotifyPropertyChanged,那么您所有的真实视图模型都可以从 ViewModelBase 继承。

    我还创建了一个在 VM 中使用的名为 TestModel 的类,但将其留空。该模型是您放置代码以与 DB 对话的地方,或者我所做的就是调用与我的 DB 对话的 WCF 服务。

    5) 最后,SelectedItem 是 ItemSource 中被选中的实际对象,而 SelectedValue 是 SelectedValuePath 的值。 在上面的示例中,我创建了一个简单的 String 集合,但假设您有一个具有多个属性的自定义对象集合,您可以将 SelectedValuePath 指定为这些属性之一。 SelectedItem 将返回整个对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-16
      • 1970-01-01
      • 2023-02-22
      • 2016-10-15
      • 1970-01-01
      • 2015-03-28
      相关资源
      最近更新 更多