简体   繁体   中英

Master Detail MVVM WPF not working

I am unable to get my bindings working on the Detail ListView. I have pasted all my MVVM pattern code below. Please help!!!

My View : DirectoryDetailView.cs

<UserControl x:Class="S2.Views.DirectoryDetailView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListView Grid.Column="0" ItemsSource="{Binding Path = DirectoryDetails}"
              IsSynchronizedWithCurrentItem="True"
              SelectedItem="{Binding SelectedDirName, Mode=TwoWay}">
        <ListView.View>
            <GridView>
                <GridViewColumn DisplayMemberBinding="{Binding Path = FileName}"
                                Header="File Name"/>
            </GridView>
        </ListView.View>
    </ListView>
    <ListView Grid.Column="1" Margin="10,0,0,0" ItemsSource="{Binding Path = DirectoryDetails}">
        <ListView.View>
            <GridView>
                <GridViewColumn DisplayMemberBinding="{Binding Path = FileDetails.Length}"
                                Header="Length"/>
                <GridViewColumn DisplayMemberBinding="{Binding Path = FileDetails.LastAccessTime}"
                                Header="LastAccessTime"/>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

My Model :

public class DirectoryModel : INotifyPropertyChanged
{
    private string _fileName;
    private DateTime _createdTime;

    public string FileName
    {
        get
        {
            return _fileName;
        }
        set
        {
            _fileName = value;
            RaisePropertyChanged("FileName");
        }
    }

    private IEnumerable<FileDetails> _fileDetails;

    public IEnumerable<FileDetails> FileDetails
    {
        get
        {
            return _fileDetails;
        }
        set
        {
            _fileDetails = value;
            RaisePropertyChanged("FileDetails");
        }

    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    protected void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = PropertyChanged;

        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class FileDetails
{
    public long Length { get; set; }

    public DateTime LastAccessTime { get; set; }
}

My ViewModel:

public class DirectoryViewModel : BaseViewModel
{
    private IEnumerable<DirectoryModel> _directoryDetails;

    public IEnumerable<DirectoryModel> DirectoryDetails
    {
        get
        {
            var service = GetService<IDirectoryService>();
            _directoryDetails = service.GetDirectoryDetails();
            return _directoryDetails;
        }
        set
        {
            if(_directoryDetails != value)
            {
                _directoryDetails = value;
                base.RaisePropertyChanged("DirectoryDetails");
            }
        }
    }

    private DirectoryModel _selectedDirName;

    public DirectoryModel SelectedDirName
    {
        get
        {
            return _selectedDirName;
        }
        set
        {
            _selectedDirName = value;
            base.RaisePropertyChanged("SelectedDirName");
        }
    }
}

Please let me know, what am I doing wrong?

Thanks, AG

I cant remember where i got this technique from but its really useful when used to debug bindings

add a class to the project called Debugconverter

public class DebugConverter : IValueConverter {
  public object Convert(object value,
     Type targetType, object parameter,
     System.Globalization.CultureInfo culture) {

     return value; //set the breakpoint here
  }

  public object ConvertBack(object value,
   Type targetType,
   object parameter,
   System.Globalization.CultureInfo culture) {

     return value;
  }

}

then i add a reference to it in app.xaml

     <currentProjectNamespace:DebugConverter
        x:Key="debugConverter" />

then use it in a binding,

Binding="{Binding Path=PropertyName, Converter={StaticResource debugConverter}}"

when the binding happens you get a breakpoint hit, i would be screwed without it. Also check the output window, there is alist of binding failures there.

Hard to say without seeing the XAML, but my first thoughts are either 1) you have not set the DataContext property to the ViewModel or 2) you have some syntax issue in the Binding itself.

You should use ObservableCollection instead of IEnumerable<DirectoryModel> to support DataBinding. I'm also not sure the implementation of your DirectoryDetails getter is beneficial. Your setter sets the private variable directly and fires the PropertyChanged event - this is proper. But your getter also sets the variable directly, bypassing the PropertyChanged event. Not to mention that you have a getter doing the work of a setter, which is probably a bad idea on several levels. I think you would be better to simplify your getter and have it just return the private variable. Do you really need to retrieve teh details everytime or can you use the local variable?

I would also point out that you do not need to implement INotifyPropertyChanged on your Model: the ViewModel needs this interface to support DataBinding, but there is no real value in adding it to the Model class.

would be helpful to know what the problem is... never the less, the questions i would ask are :-

are your getters being hit (put a breakpoint in them)?

is the first list view working, and the second one not?

if it is only the second that is failing i would guess that the problem is that you are trying to bind two columns to the property IEnumerable FileDetails, and then you are trying to follow a property path on a IEnumerable, which will not work, as it is a group of objects, not one. have you copied and pasted your code from the listview above and not set the items source correctly?

what is in your output window when you run? it usually tells you that a binding path could not be found. if you follow the debug converter suggestion above, you can find out what you are binding to (if anything)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM