2015-12-23 2 views
1

Я пытаюсь изменить ColumnSpan на основе значения из моего ViewModel в UWP для Windows 10 с помощью следующего:Bind ColumnSpan в XAML в универсальное приложение для Windows 10

<Setter Target="ProgramView.ColumnSpan" Value="{Binding 
IsProgramViewVisible, Converter={StaticResource OneIfVisibleConverter}}"/> 

Я имеющий 2 проблемы :

a) Это не позволяет мне связывать b) Он не может найти конвертер, даже если он объявлен в ресурсах моей страницы.

Когда я двигаю курсор выше, он выводит сообщение об ошибке:

Catastrophic Failure: (Exception from HRESULT: 0X8000FFFF (E_UNEXPECTED)

ошибка происходит определить ли я мой конвертер или нет, поэтому я предполагаю, что проблема с привязкой.

Есть ли способ, которым я могу это достичь?

Спасибо.

+0

Возможно, вы захотите ознакомиться с этим http://blog.galasoft.ch/posts/2012/09/adventures-in-windows-8-placing-items-in-a-gridview-with-a- columnpan-or-rowspan/ – bit

+0

@bit спасибо за это. Я нашел эту статью (все еще открытую в своем браузере), но я думал, что это было слишком сложно для того, чего я хотел достичь, но я прочитаю ее более подробно и посмотрю, смогу ли я понять и понять базовую концепцию и применить ее к мое решение. – Thierry

+0

На этой странице перейти в раздел * А теперь для ColumnSpan!* и это, скорее всего, то, что вам понадобится – bit

ответ

0

Поскольку мы не можем предоставить точное решение, не видя ваш код.

Вот список проверки вы можете следовать, чтобы выяснить, ошибка:

1.Debug ваш конвертер и проверить, если он возвращается требуемое значение для всех тестовых случаев.

2.Проверьте, все ли имена правильные и нет опечатки в ur xaml.

Вот реализация для связывания диапазона столбцов с vm и его обновления с помощью команды, связанной с событием click.

<Page.Resources> 
     <local:BoolToColumnSpanConverter x:Key="BoolToColumnSpanConverter" /> 
    </Page.Resources> 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
     <Grid.DataContext> 
      <local:Items /> 
     </Grid.DataContext> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="100" /> 
      <ColumnDefinition Width="100" /> 
      <ColumnDefinition Width="100" /> 
      <ColumnDefinition Width="100" /> 
     </Grid.ColumnDefinitions> 
     <Rectangle HorizontalAlignment="Stretch" 
         VerticalAlignment="Stretch" 
         Fill="Red" 
         Grid.ColumnSpan="{Binding span, Converter={StaticResource BoolToColumnSpanConverter}}" /> 
     <Button Click="Button_Click" 
        Content="change span" 
        Grid.ColumnSpan="2" 
        Grid.Column="2" 
        Margin="5" 
        Command="{Binding ChangeSpanCommand, Mode=OneWay}" /> 
    </Grid> 

код позади:

Преобразователь просто преобразует верно 2 и ложь 1

Команда привязана к методу в VM под названием UpdateSpan который только превращает логическое обратное ,

Когда кнопка нажата, так как она связана с командой команда называется, так как он просто возвращает новый RelayCommand с UpdateSpan в качестве параметра этот метод выполняется .. который будет обновлять калибровочный булево запуска изменение, которое уведомляется Системой через событие OnPropertyChanged, и преобразователь значения выполняется, превращая столбцы в 1 и 2.

public class BoolToColumnSpanConverter : IValueConverter 
    { 
     public object Convert(object value , Type targetType , object parameter , string language) 
     { 
      var b = (bool)value; 

      return b ? 2 : 1; 
     } 

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


    public class Items : INotifyPropertyChanged 
    { 
     private bool _span; 
     public bool span 
     { 
      get { return _span; } 
      set 
      { 
       if (value != _span) _span = value; 
       OnPropertyChanged(); 
      } 
     } 

     public ICommand ChangeSpanCommand { 
      get 
      { 
       return new RelayCommand(() => UpdateSpan()); 
      } 
     } 

     public Items() 
     { 
      span = true; 
     } 

     public void UpdateSpan() 
     { 
      span = !span; 
     } 

     #region Notify Property Changed Members 
     public event PropertyChangedEventHandler PropertyChanged; 
     private void OnPropertyChanged([CallerMemberName]string propertyName = null) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this , new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
     #endregion 
    } 

    public class RelayCommand : ICommand 
    { 
     public event EventHandler CanExecuteChanged; 

     public bool CanExecute(object parameter) 
     { 
      return true; 
     } 

     public void Execute(object parameter) 
     { 
      this._action(); 
     } 

     private Action _action; 

     public RelayCommand(Action action) 
     { 
      this._action = action; 
     } 
    } 
+0

Привет, Akash, спасибо за отзыв и извините за недостаток кода. Я думал, что обеспечить вышеуказанный код было бы достаточно. Конвертер определенно правильный, поскольку я тестировал в других частях моего приложения, чтобы убедиться, что он был прав. Также мои свойства также правильны, поскольку я вижу, как они меняются соответственно, поскольку я показывал их для целей тестирования. Прочитав немного, я думаю, что код, который я предоставил, будет работать только с WPF, а не с UWP! Я нашел сообщение о том, что триггеры больше не доступны в приложениях Windows Store с Windows 8. – Thierry

+0

Сообщение MSDN: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/77604041-b991-4f1e -9adb-78c701ac4d9a/triggers-arent-in-windows-8-xaml? Forum = winappswithcsharp, и один из предоставленных ответов заключается в том, что я в основном должен использовать VisualState. Я прочитаю это и посмотрю, смогу ли я заставить его работать таким образом. Я опубликую обновление в любом случае. – Thierry

+0

Хм .. вам следует использовать визуальный диспетчер состояний, а затем :) .. и не забудьте разместить визуального менеджера состояний в конце вашего дерева визуализации, чтобы убедиться, что он не производит никаких ошибок .. однажды у меня возникли проблемы, когда он не сделал узнайте имя текстового блока, которое было объявлено под ним в дереве –

0

Вот ответ на мою проблему.

Привязка непосредственно в сеттере не допускается для универсального приложения (Windows Store & Windows Phone Apps), но работает нормально с WPF.

<Setter Target="ProgramView.ColumnSpan" Value="{Binding 
IsProgramViewVisible, Converter={StaticResource OneIfVisibleConverter}}"/> 

Triggers/DataTriggers не поддерживаются в XAML и был заменен VisualStateManager как объяснено в DataTriggers in WinRT пост в StackOverflow.

я нашел различные объяснения о том, как решить эту проблему, так вот несколько ссылок, которые могут также оказаться полезными:

Так что мое решение как упомянутым выше, было использование VisualStateManager, более конкретно, `DataTriggerBehavior.

Одна ошибка, которая стоила мне много времени, заключалась в том, чтобы попытаться использовать ее в сочетании с существующим AdaptiveTrigger MinWindowWidth, поскольку я хотел установить свой VisualState на основе размера и на основе привязанного свойства. Это оказалось кошмаром, и это позор, что нет лучше смесь 2. Может быть, есть решение, и я до сих пор что-то отсутствует, но сейчас мое решение было следующим:

  1. Определите свои различные VisualStates и устанавливать различные свойства в нем:

    <VisualState x:Name="ListOnly"> 
        <VisualState.Setters> 
         <Setter Target="ProgramList.(Grid.Column)" Value="0" /> 
         .... 
        </VisualState.Setters> 
    </VisualState> 
    
  2. Проверьте ориентацию и ширину моего приложения от MainPage.xaml в случае Page_SizeChanged и создать статическое свойство в App.cs и установить его из там:

    private void Page_SizeChanged(object sender, SizeChangedEventArgs e) 
    { 
        if (ApplicationView.GetForCurrentView().Orientation == 
        ApplicationViewOrientation.Landscape) 
        { 
         App.IsLandscape = (ApplicationView.GetForCurrentView() 
         .VisibleBounds.Width < 600) ? false : true; 
        } 
        else 
        { 
         App.IsLandscape = false; 
        } 
    } 
    
  3. Из соответствующей страницы, загруженной в Рамках MainPage т.е. ListPage.xaml, например, я создал функцию под названием SizeChanged в соответствующих ViewModel т.е. ListPageViewModel, и я называю это внутри события Page_SizeChange страницы:

    private void Page_SizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs e) 
    { 
        this.GetViewModel.SizeChanged(); 
    } 
    
  4. метод SizeChange в соответствующем ViewModel изменит свойство, который привязываться к DataTrigger на основе ориентации и размера моего приложения:

    public void SizeChanged() 
    { 
        if (!App.IsLandscape) 
        { 
         ... 
         this.ActivePart = ActivePartEnum.ListOnly.ToString(); 
         ... 
        } 
        else 
        { 
         ... 
         this.ActivePart = ActivePartEnum.Both.ToString(); 
         ... 
        } 
    } 
    
  5. Наконец в соответствующей XAML страницы, кал л DataTriggerBehaviour:

    <Interactivity:Interaction.Behaviors> 
        <Core:DataTriggerBehavior Binding="{Binding ActivePart}" 
        ComparisonCondition="Equal" Value="ListOnly"> 
         <Core:GoToStateAction StateName="ListOnly" /> 
        </Core:DataTriggerBehavior> 
        .... 
    </Interactivity:Interaction.Behaviors> 
    

С выше, вы должны быть в состоянии применить определенный шаблон, основанный на ориентации и размера вашего приложения и может быть расширен, если это необходимо. Одна вещь, которую я буду изучать дальше, - это поведение, но не может заставить ее работать, и ей пришлось двигаться дальше, но это было бы еще лучше, я думаю.

Надеюсь, это поможет в любом случае и спасибо за отзывы каждого.

Смежные вопросы