2016-06-07 5 views
0

이 문제를 해결하기 위해 며칠 동안 인터넷 검색을 수행 한 결과, 여러분 중 한 명이 도움을 줄 수 있기를 기대합니다.ValueConverter가 호출 되더라도 NotifyPropertyChange가 호출 될 때 바인딩이 업데이트되지 않습니다.

Grid 컨트롤에 사용자 지정 종속성 속성이 있습니다. Observable Collection을 처음 생성 할 때 올바르게 업데이트됩니다. 그러나 컬렉션이 업데이트 될 때 (단순화 된 예제에서 Update 버튼을 누름) NotifyPropertyChanged가 호출되면 종속성 속성의 update 메소드가 호출되지 않습니다. 바인딩의 값 변환기가 호출되고 업데이트 된 데이터 (바인딩이 덮어 쓰여지지 않았 음을 나타내는 종류)가 표시됩니다.

참고 :이 항목은 Windows Universal이므로 일부 WPF 바인딩 추적 정보는 사용할 수없는 것 같습니다.

누구나 종속성 속성의 업데이트 메서드가 처음에만 호출되고 NotifyPropertyChanged가 호출되는 이유에 대해 설명해 줄 수 있습니까?

로버트 실제로 세포 수집 인스턴스를 변경하지 않기 때문에이 문제가 발생

<Page 
    x:Class="CustomBindingTest.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:CustomBindingTest" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" Loaded="Page_Loaded"> 

    <Page.Resources> 
     <local:DebugConverter x:Key="debug"/> 
    </Page.Resources> 

    <StackPanel Orientation="Vertical"> 
     <Button Height="50" Click="Button_Click">Update</Button> 
     <Grid local:GridHelpers.Cells="{Binding Path=Cells, Mode=TwoWay, Converter={StaticResource debug}}" Height="500"> 
      <Grid.RowDefinitions> 
       <RowDefinition/> 
       <RowDefinition/> 
       <RowDefinition/> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition/> 
       <ColumnDefinition/> 
       <ColumnDefinition/> 
       <ColumnDefinition/> 
       <ColumnDefinition/> 
       <ColumnDefinition/> 
      </Grid.ColumnDefinitions> 
     </Grid> 
    </StackPanel> 
</Page> 

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.IO; 
using System.Linq; 
using System.Runtime.InteropServices.WindowsRuntime; 
using Windows.Foundation; 
using Windows.Foundation.Collections; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Controls.Primitives; 
using Windows.UI.Xaml.Data; 
using Windows.UI.Xaml.Input; 
using Windows.UI.Xaml.Media; 
using Windows.UI.Xaml.Navigation; 

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 

namespace CustomBindingTest 
{ 
    /// <summary> 
    /// An empty page that can be used on its own or navigated to within a Frame. 
    /// </summary> 
    public sealed partial class MainPage : Page, INotifyPropertyChanged 
    { 
     public ObservableCollection<Cell> Cells { get; set; } 

     public MainPage() 
     { 
      this.InitializeComponent(); 
     } 

     private void Page_Loaded(object sender, RoutedEventArgs e) 
     { 
      Cells = new ObservableCollection<Cell>(); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 

      DataContext = this; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 
      Cells.Add(new Cell()); 

      NotifyPropertyChanged("Cells"); 
     } 

     #region NotifyPropertyChanged 
     public event PropertyChangedEventHandler PropertyChanged; 
     private void NotifyPropertyChanged(String info) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info)); 
      } 
     } 
     #endregion 

    } 
} 

<UserControl 
    x:Class="CustomBindingTest.Cell" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:CustomBindingTest" 
    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"> 

    <Grid Background="Green" Margin="5"> 

    </Grid> 
</UserControl> 

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Windows.UI; 
using Windows.UI.Text; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Media; 

namespace CustomBindingTest 
{ 
    public class GridHelpers 
    { 
     #region Cells Property 

     /// <summary> 
     /// Adds the Cell objectss to Grid. 
     /// </summary> 
     public static readonly DependencyProperty CellsProperty = 
      DependencyProperty.RegisterAttached(
       "Cells", typeof(ObservableCollection<Cell>), typeof(GridHelpers), 
       new PropertyMetadata(null, CellsChanged)); 

     // Get 
     public static ObservableCollection<Cell> GetCells(DependencyObject obj) 
     { 
      return (ObservableCollection<Cell>)obj.GetValue(CellsProperty); 
     } 

     // Set 
     public static void SetCells(DependencyObject obj, ObservableCollection<Cell> value) 
     { 
      obj.SetValue(CellsProperty, value); 
     } 

     // Change Event - Add the Cells 
     public static void CellsChanged(
      DependencyObject obj, DependencyPropertyChangedEventArgs e) 
     { 
      if (!(obj is Grid) || e.NewValue == null) 
       return; 

      Grid grid = (Grid)obj; 

      List<Cell> cells = ((ObservableCollection<Cell>)e.NewValue).ToList(); 

      if (cells != null) 
      { 
       if (cells.Count() == 0) 
       { 
        ShowEmpty(grid); 
       } 
       else 
       { 
        int rowCount = grid.RowDefinitions.Count(); 
        int colCount = grid.ColumnDefinitions.Count(); 

        for (int row = 0; row < rowCount; row++) 
        { 
         for (int col = 0; col < colCount; col++) 
         { 
          int index = (row * colCount) + col; 
          if (index < cells.Count()) 
          { 
           Cell cell = cells[index]; 
           Debug.WriteLine("Row {0} Col {1} Cell {2}", row, col, index); 
           cell.SetValue(Grid.ColumnProperty, col); 
           cell.SetValue(Grid.RowProperty, row); 
           grid.Children.Add(cell); 
          } 
         } 
        } 
       } 
      } 
     } 

     private static void ShowEmpty(Grid grid) 
     { 
      TextBlock text = new TextBlock(); 
      text.Text = "[Empty Grid]"; 
      text.FontSize = 24.0; 
      text.Foreground = new SolidColorBrush(Colors.Red); 
      text.FontWeight = FontWeights.Bold; 
      text.SetValue(Grid.ColumnProperty, 0); 
      text.SetValue(Grid.RowProperty, 0); 
      grid.Children.Add(text); 
     } 

     #endregion 
    } 
} 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Windows.UI.Xaml.Data; 

namespace CustomBindingTest 
{ 
    class DebugConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, string language) 
     { 
      return value; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, string language) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 
+0

댓글로 업데이트하는 대신 소식을 직접 수정할 수 있습니다. 이것은 앞으로 질문을 더 읽기 쉽게 할 것입니다. – AlexDrenea

답변

1

, 당신은 그냥 항목을 추가한다.

초기에는 종속성 속성 값이 null입니다. Page_Loaded 이벤트에서 ObservableCollection()의 새 인스턴스를 만들고 DataContext를 설정하면 바인딩을 업데이트하고 종속성 속성 값을 해당 인스턴스로 설정합니다.

Button_Click 이벤트에서는 단순히 컬렉션에 새 항목을 추가하지만 Cells 인스턴스를 변경하지 않으므로 종속성 속성이 속성 변경 이벤트를 발생시키지 않습니다. 이벤트를 발생시키는 경우에도 프레임 워크는 인스턴스를 실제로 변경하지 않아도 호출을 무시합니다.

나는 당신이 달성하고자하는 것이 무엇인지 확실하지 않지만 ObservableCollection으로 셀을 실제로 사용하지 않는다는 사실을 알고 있습니다. 종속성 ChangedCells 이벤트의 List <에 캐스트하고 있기 때문입니다. 이 문제를 해결하려면 Cell 객체를 List <>으로 변경하고 업데이트 버튼을 누를 때마다 다시 만들어보십시오.

+0

감사합니다 알렉스 - 크게 감사드립니다. NotifyPropertyChange는 바인딩이 걱정되는 한 컬렉션이 변경되지 않았더라도 뷰를 업데이트하도록했습니다. 이것은 분명히 틀렸다! 또한 내가 제공 한 코드는 실제 프로젝트에서 Cells 객체가 실제로 다르게 사용되도록 문제를 설명하기위한 간단한 예제였습니다. 도와 줘서 고마워. – Robert

+0

방금 ​​https://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx에서 설명서를 찾았습니다. _Represents 항목이 추가 될 때 알림을 제공하는 동적 데이터 수집 제거되거나 전체 목록이 새로 고쳐질 때. – Robert

+0

로버트가 도움이되었다고 반갑습니다. 그것이 당신이 찾고있는 것이라면 그 게시물을 답으로 표시하는 것을 잊지 마십시오! – AlexDrenea

관련 문제