I try to build a wpf based application with datagrid and itemsource is bound to an object.
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>
and the generated source code
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;
}
}
}
}
and the viewModel(i not gonna show the whole code here, just what is necessary)
public class FolderViewModel : UploadViewModelBase
{
public BindingList<Folder> Folders { get; set; }
public FolderViewModel(string filename)
: base(filename)
{
}
Here I use bindinglist generics type collection instead observecollection, for observe change on the collection.
And the last file, the model
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); }
}
}
the whole problem is here, when I change the content from a row, it does not change on the collection object. What i do wrong?
You have had some confusion with data binding. Here are some tips:
Two-Way Binding
s are used on the controls that display and can edit data bound values, not the container control's properties... this means that there is no point on setting Mode="Two-Way"
on an ItemsSource
property, because if you look at the ItemsControl.ItemsSource
Property page on MSDN, you'll see that it only supports One-Way Binding
s.
As mentioned, setting Mode="Two-Way"
should only be used on controls that can display and can edit the data bound values. However if you look on the TextBox.Text
property page on MSDN, you should see a section named Dependency Property Information . In this section, you can see that the Textbox.Text
property binds Two-Way
by default, so you never have to apply that setting to it.
So, while you say that your solution was to use the following:
<TextBox Grid.Column="0" Text="{Binding Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ... />
I'm fairly sure that it was just the UpdateSourceTrigger
property that you needed to set, because as we all know now, setting Mode=TwoWay
on the Textbox.Text
property does nothing:
<TextBox Grid.Column="0" Text="{Binding Path, UpdateSourceTrigger=PropertyChanged}" ... />
I can see at least the following two problems in your code:
DataGrid
never modifies the ItemsSource
reference itself (only its "contents"), therefore you should not set Mode=TwoWay
. BindingList<T>
does not implement this interface. Therefore, you better use ObservableCollection<T>
, which implements this interface. Furthermore,
public BindingList Folders { get; set; }
seems to be incorrect, if your BindingList
is this one: MSDN documentation for BindingList . It probably should be
public BindingList<Folder> Folders { get; set; }
But maybe it is just a typo in your question.
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.