2011-07-22 25 views
8

Mã của tôi không thành công ở lúc khởi động vì các mảng giá trị trong Converter đó được gọi bởi Multibindingkhông được điền với giá trị hợp lý nhưng có một giá trị củaDependencyProperty.UnsetValue.WPF MultiBinding trong Convertor thất bại ==> DependencyProperty.UnsetValue

có một cái nhìn tại Convertor và cũng thấy nơi mà tôi nhận được lỗi

public class ButtonColorConverter : IMultiValueConverter 
    { 
     public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
     { 
      string val1 = string.Format(" {0} ", values[0]); 
      string val2 = (string)values[1]; **//Here i am getting ==> {DependencyProperty.UnsetValue}** 
      return val1.Equals(val2) 
       ? Brushes.NavajoWhite 
       : Brushes.White; 
     } 

     public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

Bạn có thể tải full code hoặc xem mã số của tôi đoạn mã theo bên dưới.

MainWindow.xaml

<Window x:Class="DataPager.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" 
     xmlns:Local="clr-namespace:DataPager.Convertor_For_BackGround"> 
    <Grid> 
     <Grid.Resources> 
      <Local:ButtonColorConverter x:Key="currentPageSetter"/> 
     </Grid.Resources> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="36*" /> 
      <RowDefinition Height="275*" /> 
     </Grid.RowDefinitions> 
     <ItemsControl Name="pageControl" ItemsSource="{Binding Path=PageCollection}" Grid.Row="0"> 
      <ItemsControl.Template> 
       <ControlTemplate TargetType="ItemsControl"> 
        <Border > 
         <StackPanel> 
          <ItemsPresenter></ItemsPresenter> 
         </StackPanel> 
        </Border> 
       </ControlTemplate> 
      </ItemsControl.Template> 
      <ItemsControl.ItemsPanel x:Uid="pageItemTemplate"> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Horizontal"/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <Button x:Name="pageNumberButton" Margin="3,4" Content="{Binding Path=Page_Number}"> 
         <Button.Background> 
          <MultiBinding Converter="{StaticResource currentPageSetter}"> 
           <Binding Path="Page_Number" /> 
           <Binding Path="CurrentPage.Page_Number" /> **//This Binding not resolves properly** 
          </MultiBinding> 
         </Button.Background> 
        </Button> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 

     </ItemsControl> 
     <TextBox Text="{Binding Path=CurrentPage.Page_Number,Mode=TwoWay, FallbackValue=asdf}" Grid.Row="1" Height="23" Margin="79,62,257,0" Name="textBox1" VerticalAlignment="Top" Width="167" /> 
    </Grid> 
</Window> 

MainWindow.xaml.cs

public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 


      MyPageViewModel = new PageViewModel(); 

      MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format(" {0} ",0))); 
      MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format(" {0} ",1))); 
      MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format(" {0} ",2))); 
      MyPageViewModel.PageCollection.Add(new PageNumberViewModel(string.Format(" {0} ",3))); 

      InitializeComponent(); 
     } 

     public PageViewModel MyPageViewModel 
     { 
      get 
      { 
       return this.DataContext as PageViewModel; 
      } 
      set 
      { 
       this.DataContext = value; 
      } 
     } 
    } 

Và đây là lớp ViewModel.

PageViewModel.cs

public class PageViewModel:ViewModelBase 
    { 
     private ObservableCollection<PageNumberViewModel> m_pageCollection = new ObservableCollection<PageNumberViewModel>(); 
     private PageNumberViewModel m_currentPage = new PageNumberViewModel(string.Format(" {0} ",0)); 

     public PageViewModel() 
     { 
      m_currentPage = new PageNumberViewModel(string.Format(" {0} ", 1000)); 
     } 

     public PageNumberViewModel CurrentPage 
     { 
      get 
      { 
       return this.m_currentPage; 
      } 
      set 
      { 
       if (m_currentPage == value) 
        return; 
       this.m_currentPage = value; 
       base.OnPropertyChanged("CurrentPage"); 
      } 
     } 
     public ObservableCollection<PageNumberViewModel> PageCollection 
     { 
      get 
      { 
       return this.m_pageCollection; 
      } 
      set 
      { 
       if (m_pageCollection == value) 
        return; 
       this.m_pageCollection = value; 
       base.OnPropertyChanged("PageCollection"); 
      } 
     } 
    } 

PageNumberViewModel.cs

public class PageNumberViewModel : ViewModelBase 
    { 
     private string m_pageNumber; 

     public PageNumberViewModel()    
     { 

     } 
     public PageNumberViewModel(string pageNumgerArg) 
     { 
      this.m_pageNumber = pageNumgerArg; 
     } 

     public string Page_Number 
     { 
      get { return m_pageNumber; } 
      set 
      { 
       if (m_pageNumber == value) 
        return; 
       m_pageNumber = value; 
       OnPropertyChanged("PageNumber"); 
      } 
     } 

    } 
+1

Ngay cả khi không nhìn sâu hơn vào mã của bạn, tôi rất muốn đề nghị thử nghiệm đầu tiên trước khi bạn thực hiện (string) giá trị [1] (luôn luôn cẩn thận với "con số ma thuật") nếu a) các giá trị []! = null và b) thực sự chứa đối tượng ở chỉ mục 1 (hoặc ít nhất là giá trị.Length> 0) và c) đối tượng đó thực sự có loại mong muốn STRING. Trình kích hoạt có thể kích hoạt thường xuyên và sau đó chứa các giá trị khác nhau hơn bạn có thể mong đợi, vì vậy hãy luôn kiểm tra Mảng của bạn trước khi bạn sử dụng chúng trực tiếp. Điều đó có thể đã giúp bạn ngăn chặn các ngoại lệ của bạn. –

Trả lời

7

Khi bạn đặt danh sách trong bất kỳ ItemsSource nào, DataContext của DataTemplate cho các mục riêng lẻ sẽ từng mục trong danh sách.

Đúng là TextBlock bạn ràng buộc đang làm việc một cách chính xác, bởi vì DataContext được thiết lập để đối tượng chính của bạn: PageViewModel

Nhưng trong DataTemplate của bạn DataContext sẽ được thiết lập để PageNumberViewModel, vì đây là những mặt hàng trong bộ sưu tập của bạn.

Chính vì vậy, các ràng buộc để Path=CurrentPage.Page_Number sẽ dẫn đến UnsetValue, vì CurrentPage không phải là một tài sản của PageNumberViewModel

Hy vọng điều này làm rõ mọi thứ!

Nếu bạn thực sự muốn liên kết với các tài sản CurrentPage của DataContext của Window của bạn, hãy xem xét sử dụng một ElementName ràng buộc:

Đưa cửa sổ một cái tên, ràng buộc để

<Binding ElementName="name" Path="DataContext.CurrentPage.Page_Number" /> 

hoặc sử dụng một RelativeSource ràng buộc:

<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" Path="DataContext.CurrentPage.Page_Number" /> 
+1

Cảm ơn bạn rất nhiều ........ Đây là những gì chính xác tôi muốn ... tôi vừa thay đổi đường dẫn ràng buộc như bạn đã đề xuất .. và vấn đề đang được giải quyết ..... một lần nữa cảm ơn bạn rất nhiều. ..... –

+0

Bạn được chào đón! Mừng vì tôi có thể giúp! :) – Arcturus

+1

Tuyệt vời! Thú vị vấn đề. Hữu ích cho tôi cũng như @Arcturus – Ramankingdom

5

Dường như bạn có thể không có DataContext đúng để giải quyết con đường CurrentPage.Page_Number. Một cách tốt để gỡ lỗi các loại điều này là để loại bỏ các con đường để bạn có thể kiểm tra việc DataContext trong chuyển đổi giá trị của bạn:

<Binding Path="." /> 

Sau đó thiết lập một breakpoint trong ButtonColorConverter của bạn và có một cái nhìn chính xác những gì bạn đang cố gắng để chuyển đổi.

+0

Bạn có thể thấy ở bên cạnh mã của tôi khi tôi ràng buộc 'CurrentPage.Page_Number' này vào thuộc tính 'Text'' của TextBox', nó hoạt động tốt. nó chỉ đưa ra ngoại lệ nếu chúng ta sử dụng nó trong Multibinding với Convertor –

+1

Có, nhưng không phải là ràng buộc nội dung của bạn, Content = "{Binding Path = Page_Number}", ảnh hưởng đến DataContext của Button.Background? – ColinE

+0

Ya @ColinE, khi tôi có degug theo bạn đã đề nghị ... tôi đang nhận '{DataPager.ViewModel.PageNumberViewModel}' thay vì '{DataPager.ViewModel.PageViewModel}' mà tôi đã gán là 'DataContext' Cảm ơn ..... –

0

Tôi vừa thay đổi trong MainWindow.xaml theo một yêu cầu của Mr.Arcturus và wo của nó rking tốt.

Cảm ơn bạn rất nhiều Mr.Arcturus.

bạn có thể thấy ManiWindow.xaml sau chage

<Window x:Class="DataPager.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" 
     xmlns:Local="clr-namespace:DataPager.Convertor_For_BackGround"> 
    <Grid> 
     <Grid.Resources> 
      <Local:ButtonColorConverter x:Key="currentPageSetter"/> 
     </Grid.Resources> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="36*" /> 
      <RowDefinition Height="275*" /> 
     </Grid.RowDefinitions> 
     <ItemsControl Name="pageControl" ItemsSource="{Binding Path=PageCollection}" Grid.Row="0"> 
      <ItemsControl.Template> 
       <ControlTemplate TargetType="ItemsControl"> 
        <Border > 
         <StackPanel> 
          <ItemsPresenter></ItemsPresenter> 
         </StackPanel> 
        </Border> 
       </ControlTemplate> 
      </ItemsControl.Template> 
      <ItemsControl.ItemsPanel x:Uid="pageItemTemplate"> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Horizontal"/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <Button x:Name="pageNumberButton" Margin="3,4" Content="{Binding Path=Page_Number}"> 
         <Button.Background> 
          <MultiBinding Converter="{StaticResource currentPageSetter}"> 
           <Binding Path="Page_Number" /> 
           **<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" Path="DataContext.CurrentPage.Page_Number" />** 
          </MultiBinding> 
         </Button.Background> 
        </Button> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 

     </ItemsControl> 
     <TextBox Text="{Binding Path=CurrentPage.Page_Number,Mode=TwoWay, FallbackValue=asdf}" Grid.Row="1" Height="23" Margin="79,62,257,0" Name="textBox1" VerticalAlignment="Top" Width="167" /> 
     <Button Content="Button" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="121,110,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" /> 
    </Grid> 
</Window> 
5

Tôi cũng gặp phải vấn đề này và tìm ra giải pháp trong một bài (https://stackoverflow.com/a/3139397/500099). Điều quan trọng là sử dụng FallbackValue = "" bất động sản như thế này:

<MultiBinding Converter="{StaticResource StringFormatConverter}"> 
    <Binding Path="ResultValueControl.Min" FallbackValue=""/> 
    <Binding Path="Format" /> 
</MultiBinding> 
5

DependencyProperty.UnsetValue chỉ đơn thuần là một hằng số trên lớp DependencyProperty.

Bạn có thể làm một cái gì đó như thế này:

if (values[1] == DependencyProperty.UnsetValue) 
{ 
    return null; // or default value 
} 
+1

Câu trả lời tuyệt vời không liên quan đến một kịch bản! – usefulBee

Các vấn đề liên quan