Datagrid itemssource双向数据绑定无法正常工作

时间:2014-06-26 13:56:23

标签: c# wpf xaml datagrid

我尝试使用datagrid构建基于wpf的应用程序,并将itemsource绑定到一个对象。

的Xaml

   <DataGrid ItemsSource="{Binding Folders, Mode=TwoWay}" AutoGenerateColumns="False" HorizontalScrollBarVisibility="Visible"  VerticalScrollBarVisibility="Visible">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Path" CanUserResize="False">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="260"></ColumnDefinition>
                                <ColumnDefinition Width="30"></ColumnDefinition>
                                <ColumnDefinition Width="30"></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <TextBox Grid.Column="0" Text="{Binding Path}">
                                <TextBox.Style>
                                    <Style TargetType="{x:Type TextBox}">
                                        <Style.Triggers>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Cursor" Value="Arrow"></Setter>
                                            </Trigger>
                                        </Style.Triggers>
                                    </Style>
                                </TextBox.Style>
                            </TextBox>
                        </Grid>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

和生成的源代码

   public partial class FolderControl : UserControl
    {
        public FolderViewModel FolderViewModel = new FolderViewModel("SourceFolders.xml");

        public FolderControl()
        {
            InitializeComponent();
            DataContext = FolderViewModel;
        }

        private TextBox GetTextBoxInstance(object obj)
        {
            var btn = (Button) obj;
            var parent = (Grid) btn.Parent;
            var text = (TextBox) parent.Children.Cast<UIElement>().Select(tb => tb).First();
            return text;
        }

        private void OpenFolder_OnClick(object sender, RoutedEventArgs e)
        {
            var text = GetTextBoxInstance(sender);
            Win32.FolderBrowserDialog fbd = new Win32.FolderBrowserDialog();
            Win32.DialogResult showDialog = fbd.ShowDialog();
            text.Text = fbd.SelectedPath;
        }

        private void OpenFile_OnClick(object sender, RoutedEventArgs e)
        {
            var text = GetTextBoxInstance(sender);
            Win32.OpenFileDialog ofd = new Win32.OpenFileDialog();
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                // If find the same file on collection, show msg error
                if (FolderViewModel.Folders.Any(file => file.Path == ofd.FileName))
                {
                    MessageBoxResult result = MessageBox.Show(EN.TEXT4, "Info", MessageBoxButton.OK); 
                }
                else
                {
                    text.Text = ofd.FileName;
                }
            }
        }

    }

和viewModel(我不会在这里显示整个代码,只是必要的内容)

public class FolderViewModel : UploadViewModelBase
{
    public BindingList<Folder> Folders { get; set; }

    public FolderViewModel(string filename)
        : base(filename)
    {
    }

这里我使用bindinglist泛型类型集合而不是observecollection来观察集合的变化 最后一个文件是模型

public class Folder : ObservableObject
{
    private String _path;
    private OsType _os;
    private String _strOs;

    public String Path
    {
        get { return _path; }
        set { _path = value; RaisePropertyChanged(() => this.Path); }
    }

    public OsType Os
    {
        get { return _os; }
        set { _os = value; RaisePropertyChanged(() => this.Os); }
    }

    public String StrOs
    {
        get { return _strOs; }
        set { _strOs = value; RaisePropertyChanged(() => this.StrOs); }
    }
}

整个问题就在这里,当我从一行更改内容时,它不会在集合对象上发生变化。我做错了什么?

2 个答案:

答案 0 :(得分:1)

您对数据绑定感到困惑。以下是一些提示:

Two-Way Binding用于显示的控件,可以编辑数据绑定值,而不是容器控件的属性......这意味着没有任何意义在Mode="Two-Way"媒体资源上设置ItemsSource,因为如果你查看MSDN上的ItemsControl.ItemsSource Property页面,就会发现它只支持One-Way Binding s。

如上所述,设置Mode="Two-Way"只应用于可显示并可编辑数据绑定值的控件。但是,如果您查看MSDN上的TextBox.Text property页面,您应该会看到名为依赖项属性信息的部分。在本节中,您可以看到默认情况下Textbox.Text属性绑定Two-Way,因此您永远不必对其应用该设置。

所以,虽然你说你的解决方案是使用以下内容:

<TextBox Grid.Column="0" Text="{Binding Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ... />

我相当确定它只是您需要设置的UpdateSourceTrigger属性,因为我们现在都知道,在Mode=TwoWay属性上设置Textbox.Text不会做任何事情:

<TextBox Grid.Column="0" Text="{Binding Path, UpdateSourceTrigger=PropertyChanged}" ... />

答案 1 :(得分:0)

我的代码中至少可以看到以下两个问题:

  1. DataGrid永远不会修改ItemsSource引用本身(仅限其&#34;内容&#34;),因此您不应设置Mode=TwoWay
  2. 大多数WPF旨在使用实现INotifyCollectionChanged的集合数据类型。 BindingList<T>未实现此接口。因此,您最好使用ObservableCollection<T>来实现此接口。
  3. 此外,

    public BindingList Folders { get; set; }
    

    似乎不正确,如果您的BindingList就是这个:MSDN documentation for BindingList。它应该是

    public BindingList<Folder> Folders { get; set; }
    

    但也许这只是你问题上的一个错字。