2015-09-23 6 views
0

Мой XAML:Datagrid обновление TemplateColumn источник запуска явно обновляет только первый ряд

<DataGridTemplateColumn Header=" Student ID" Width="Auto"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <TextBox x:Name="StudentIdTextBox" Text="{Binding Path=StudentID, UpdateSourceTrigger=Explicit, Mode=TwoWay}" PreviewTextInput="ID_OnPreviewTextInput" /> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn> 

Мой StudentManagementClass:

public class StudentManagement:INotifyPropertyChanged 
{ 
    private string StudId; 
    public bool Check { get; set; } 
    public int ID { get; set; } 
    public string StudentID 
    { 
     get { return StudId; } 
     set 
     { 
      StudId = value; 
      PropertyChanged(this, new PropertyChangedEventArgs("StudentID")); 
     } 
    } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Gender { get; set; } 
    public string Birthdate { get; set; } 
    public string MobileNumber { get; set; } 
    public string Year { get; set; } 
    public string Section { get; set; } 
    public string Department { get; set; } 
    public string Course { get; set; } 
    public string Semester { get; set; } 
    public List<string> AccessLevel { get; set; } 
    public string AccessLevels { get; set; } 
    public bool SetTime { get; set; } 
    public string StartDate { get; set; } 
    public string Expiration { get; set; } 
    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
} 

Пример кода:

public ObservableCollection<SM> StudentManagements { get; set; } 

Список Temp (я на самом деле просто проверяя вещи)

StudentManagements = new ObservableCollection<SM>(); 
List<string> AccessLevel = new List<string>(); 
AccessLevel.Add("a"); 
AccessLevel.Add("b"); 
AccessLevel.Add("c"); 
AccessLevel.Add("d"); 
AccessLevel.Add("e"); 
StudentManagements.Add(new SM() 
{ 
    StudentID = "1111", 
    AccessLevel = AccessLevel, 
    AccessLevels = "a,c", 
    Birthdate = "1/1/1993", 
    Course = "", 
    Department = "", 
    Expiration = "1/1/1993", 
    FirstName = "", 
    Gender = "Male", 
    LastName = "", 
    MobileNumber = "09497740052", 
    Section = "", 
    Semester = "1st", 
    StartDate = "1/1/1993", 
    Year = "2nd", 
    SetTime = true, 
    ID = 1 
}); 
StudentManagements.Add(new SM() 
{ 
    StudentID = "2222", 
    AccessLevel = AccessLevel, 
    AccessLevels = "e,d", 
    Birthdate = "1/1/1992", 
    Course = "", 
    Department = "", 
    Expiration = "1/1/1992", 
    FirstName = "", 
    Gender = "Male", 
    LastName = "", 
    MobileNumber = "09497740052", 
    Section = "", 
    Semester = "1st", 
    StartDate = "1/1/1994", 
    Year = "2nd", 
    SetTime = true, 
    ID = 1 
}); 

Кнопки Явного UpdateSource что обновляет только первую строку вместо всех редактируемых строк (Обратите внимание, что я только тестирование это, поэтому я только попробовал это на один столбец):

x = FindChild<TextBox>(AccessGrid, "StudentIdTextBox"); 
BindingExpression a = x.GetBindingExpression(TextBox.TextProperty); 
a.UpdateSource(); 

Я получил FindChild от этого парня FindChild

я довольно много имеют тот же вопрос с этим парнем, но никто не отвечает на его вопросы: dude with le same issue

А потом я просто обновить их с помощью кнопки:

AccessGrid.ItemsSource = null; 
AccessGrid.ItemsSource = StudentManagements; 

Теперь он работает немного, и мое свойство UpdateSourceTrigger установлен в явной, так что я могу сохранить изменения, как только я нажимаю на кнопку, но только первая строка обновляется, есть ли другие способы обновить свойство sourcetrigger явно ?

+0

В коде SM = StudentManagement , правильно ? –

+0

@ Emmanuel да, это было в другом проекте, который я использовал в качестве библиотеки и укоротил его: с использованием SM = DataAccess.Personnel.StudentManagement; – Bryan

ответ

0

С помощью небольшого метода поиска всех визуальных потомков (= элементов Framework, обусловленных определениями шаблонов), а некоторые функции Linq для проверки потомков являются текстовыми полями с заданным именем, вы можете явно обновить привязку для всех строк в Визуальное дерево.

Вот помощник:

public static class VisualTreeHelperExtension 
{ 
    struct StackElement 
    { 
     public FrameworkElement Element { get; set; } 
     public int Position { get; set; } 
    } 
    public static IEnumerable<FrameworkElement> FindAllVisualDescendants(this FrameworkElement parent) 
    { 
     if (parent == null) 
      yield break; 
     Stack<StackElement> stack = new Stack<StackElement>(); 
     int i = 0; 
     while (true) 
     { 
      if (i < VisualTreeHelper.GetChildrenCount(parent)) 
      { 
       FrameworkElement child = VisualTreeHelper.GetChild(parent, i) as FrameworkElement; 
       if (child != null) 
       { 
        if (child != null) 
         yield return child; 
        stack.Push(new StackElement { Element = parent, Position = i }); 
        parent = child; 
        i = 0; 
        continue; 
       } 
       ++i; 
      } 
      else 
      { 
       // back at the root of the search 
       if (stack.Count == 0) 
        yield break; 
       StackElement element = stack.Pop(); 
       parent = element.Element; 
       i = element.Position; 
       ++i; 
      } 
     } 
    } 
} 

В кнопке мыши, нужно только позвонить помощник:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    // to check : 
    MessageBox.Show(StudentManagements[1].StudentID.ToString()); 

    var textboxes = AccessGrid.FindAllVisualDescendants() 
     .Where(elt => elt.Name == "StudentIdTextBox") 
     .OfType<TextBox>(); 
    foreach (var textbox in textboxes) 
    { 
     BindingExpression binding = textbox.GetBindingExpression(TextBox.TextProperty); 
     binding.UpdateSource(); 
    } 
    // to check : 
    MessageBox.Show(StudentManagements[1].StudentID.ToString()); 
} 

Это должно помочь, удачи

+0

bruh, еще одна проблема здесь, где вы получили это 'Display (child, stack.Count);' btw, я использую страницу и '(этот родитель FrameworkElement, String name)' вызывает ошибку. Извините, я совершенно новый для wpf. – Bryan

+0

спасибо за наконечник и образец кода Брух, наконец, получил его: с момента его от другого класса косяк действительно назвать, что 'вар Textboxes = AccessGrid.FindAllVisualDescendantByNameOfType («StudentIdTextBox»);' Я использовал это вместо: 'уаг х = VisualTreeHelperExtension.FindAllVisualDescendantByNameOfType (AccessGrid, "StudentIdTextBox"); ' Еще раз спасибо bruh – Bryan

+0

Функция отображения - это только функция отладки, которую я забыл удалить. Я исправляю это сейчас. Для вызова метода FindAllVisulDescendantByNameOfType, как я это делаю, вам нужно только добавить использование NamespaceOfFindAllVisulDescendantByNameOfType; –