2011-07-22 21 views
8

Mi código falla en el arranque debido a la matriz valores en el Converter que es llamado por el Multibinding es no llena de valor apropiado, pero tienen un valor deDependencyProperty.UnsetValue.WPF en MultiBinding convertidor falla ==> DependencyProperty.UnsetValue

echar un vistazo a convertidor y también ver donde error al obtener

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(); 
     } 
    } 

Puede descargar full code o ver mis códigos de fragmento según abajo.

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; 
      } 
     } 
    } 

y esto es clases 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

Incluso sin mirar más profundamente en su código, me gustaría sugerir fuertemente a la primera prueba antes de ejecutar valores que (cuerda) [1] (siempre Cuidado con los "números mágicos") si a) los valores []! = null yb) realmente contienen un objeto en el índice 1 (o al menos values.Length> 0), yc) ese objeto realmente tiene el tipo deseado STRING. Los desencadenadores pueden disparar a menudo y luego contienen valores diferentes a los esperados, por lo que siempre verifique sus matrices antes de usarlas directamente. Eso quizás ya te ayude a evitar tus excepciones. –

Respuesta

7

Cuando establece una lista en cualquier ItemsSource, el DataContetext de DataTemplate para los elementos individuales será cada elemento de la lista.

Es cierto que su unión TextBlock está funcionando correctamente, ya que el DataContext se establece en su objetivo principal: PageViewModel

Pero en su DataTemplate la DataContext se establece en PageNumberViewModel, ya que estos son los elementos de la colección.

para ello, la unión a Path=CurrentPage.Page_Number dará lugar a UnsetValue, porque currentPage no es una propiedad de PageNumberViewModel

la esperanza que esto aclare las cosas!

Si realmente desea unirse a la propiedad currentPage de DataContext de su ventana, considere el uso de un ElementName vinculante:

Dale ventana de un nombre, se unen a

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

o utilizar un RelativeSource vinculante:

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

Muchas gracias ... Esto es exactamente lo que quería ... Acabo de cambiar el camino de encuadernación como lo ha sugerido ... y el problema se resuelve ... una vez más muchas gracias. ..... –

+0

¡De nada! ¡Me alegro de poder ayudar! :) – Arcturus

+1

¡Asombroso! Tema interesante. Útil para mí también @Arcturus – Ramankingdom

5

Parece que puede que no tenga la DataContext correcta para resolver la ruta CurrentPage.Page_Number. Una buena manera de depurar este tipo de cosas es para eliminar la ruta para que pueda inspeccionar la DataContext dentro de su convertidor de valores:

<Binding Path="." /> 

A continuación, un punto de ruptura en su ButtonColorConverter y echar un vistazo a exactamente lo que está tratando para convertir.

+0

Puede ver en el costado mi código cuando vinculo este 'CurrentPage.Page_Number' a la propiedad' Text' de 'TextBox' y funciona bien. solo da excepción si lo usamos en Multibinding con Convertor –

+1

Sí, pero ¿no es su contenido vinculante, Content = "{Binding Path = Page_Number}", que afecta al DataContext del Button.Background? – ColinE

+0

Ya @ColinE, cuando tengo degug como usted ha sugerido ... obtengo '{DataPager.ViewModel.PageNumberViewModel}' como en lugar de '{DataPager.ViewModel.PageViewModel}' que he asignado como 'DataContext' Gracias ..... –

0

acabo cambiado en MainWindow.xaml según sugerencia de Mr.Arcturus y su wo muy bien

Muchas gracias Mr.Arcturus.

se puede ver ManiWindow.xaml después 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

También me encontré con este problema y encontró una solución en otro post (https://stackoverflow.com/a/3139397/500099). La clave es usar la FallbackValue = "" propiedad como esta:

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

DependencyProperty.UnsetValue no es más que una constante en la clase DependencyProperty.

Usted puede hacer algo como esto:

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

¡Excelente respuesta que no está ligada a un escenario! – usefulBee

Cuestiones relacionadas