2017-04-18 42 views
1

不確定是否適當地設置了問題的格式,請讓我知道如果沒有。但我試圖簡單地將背景顏色綁定到我的視單元中的值。實際上,我有這個工作。問題是當我更新一個值時,我看不到背景顏色的變化。實現有點複雜,但這是我的代碼。嘗試在OnBindingContextChanged中使用ListView(回收緩存策略)的值轉換器

ViewCell(OnBindingContextChanged)

... 
ShowReadOverlay.SetBinding(Xamarin.Forms.VisualElement.BackgroundColorProperty, new Xamarin.Forms.Binding(".", Xamarin.Forms.BindingMode.TwoWay, new XamarinMobile.Converters.GridCellBackgroundColorConverter(), null, null, null)); 
... 

所以基本上我只是建立我的佈局。我決定只發布在我的OnBindingContextChanged方法中設置綁定的相關代碼。如果任何人需要任何其他代碼,我很樂意添加它,只是不知道它是否相關。我的ViewCell類是一個簡單的類,它繼承了ViewCell

這裏是我的轉換器:

public class GridCellBackgroundColorConverter : Xamarin.Forms.IValueConverter 
{ 
    #region IValueConverter Members 

    public object Convert(object value, Type targetType, object parameter, 
     System.Globalization.CultureInfo culture) 
    { 
     try 
     { 

      var cell = (XamarinMobile.ViewModels.GridCellViewModel)value; 

      if(cell.HasRead) 
      { 
       //return with shadow 
       return Xamarin.Forms.Color.FromRgba(0,0,0,0.6); 
      } else 
      { 
       //return no shadow 
       return Xamarin.Forms.Color.FromRgba(0, 0, 0, 0.0); 
      } 

     } catch(System.Exception ex) 
     { 
      return null; 
     } 

    } 

    public object ConvertBack(object value, Type targetType, object parameter, 
     System.Globalization.CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 

    #endregion 
} 

簡單。有用。現在,這是棘手的部分。所以我描述的網格是一個包含故事單元的列表視圖。用戶將點擊一個圖像,將他們帶到故事頁面。當用戶在故事頁面中時,他們可以回到網格去看另一個故事,或者向左或向右滑動,然後他們可以通過這種方式獲得另一個故事。當用戶從我們的網格轉到故事頁面時,單元格會正常更新。但是如果用戶不是從網格滑動到另一個故事,那就是我的問題所在。在我的故事頁面中,我有邏輯遍歷網格單元格,並找到您當前所在的故事(您所滑動的故事)並查看它是否在網格中,如果它在網格中,我更新單元格的HasRead屬性。因此:

  //find the cell in the grid (if exists) 
      ViewModels.GridCellViewModel cell = App.GridCells.Where(x => x.StoryId == App.Story.StoryId).FirstOrDefault(); 
      if (cell != null) 
      { 
       cell.HasRead = true; 
      } 

這可以工作,但是...它不會觸發值轉換器來更改屬性。我究竟做錯了什麼?我怎樣才能得到它,以便我可以更新一個屬性,並讓它觸發我的價值轉換器?

+0

什麼?該死的..甚至沒有關於如何通過onbindingcontext更改綁定視單元的一點見解? – jdmdevdotnet

回答

0

我的猜測是,你的轉換器不會觸發,因爲你已經技術上綁定到視單元本身,而不是HasRead屬性。當你設置HasRead時,它會(假設它正在實現INotifyPropertyChanged)觸發一個PropertyChangedEvent,它會觸發綁定並調用值轉換器。但是,由於您的綁定指向視單元本身,因此只有在該對象的其他位置發生更改並忽略屬性更改時纔會觸發。

一個可能的解決方案是將綁定更改爲指向HasRead(而不是'。'),並更新您的轉換器以直接期望布爾值而不是取入視單元。無論如何,這對轉換器來說都是更好的做法。

這就是說,這並不是真正遵循通常爲xamarin表單應用推薦的mvvm模式。我的建議是建立一個視圖模型,該視圖模型具有一個保存故事模型的屬性(如果您需要邏輯,請將其包含在自己的StoryViewModels中),並確保VM和Model類實現INotifyPropertyChanged。將虛擬機作爲頁面的數據上下文,將列表綁定到你的列表視圖源,你的列表視圖項目模板內容將綁定到每個單獨的故事。每個故事可以有一個HasRead屬性,通過更新的轉換器綁定到背景顏色。

像這樣:

<ContentPage 
x:Class="Stack_Stories.MainPage" 
xmlns="http://xamarin.com/schemas/2014/forms" 
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
xmlns:local="clr-namespace:Stack_Stories"> 
<ContentPage.BindingContext> 
    <local:StoriesViewModel x:Name="VM" /> 
</ContentPage.BindingContext> 
<ContentPage.Resources> 
    <ResourceDictionary> 
     <local:StoryReadBackgroundColorConverter x:Key="HasReadColor" /> 
    </ResourceDictionary> 
</ContentPage.Resources> 

<ListView ItemsSource="{Binding Stories}"> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <ViewCell> 
       <Grid x:Name="StoryGrid" BackgroundColor="{Binding HasRead, Converter={StaticResource HasReadColor}}"> 
        <Button Command="{Binding ToggleReadCommand}" Text="{Binding Name}" /> 
       </Grid> 
      </ViewCell> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

public class StoryViewModel : INotifyPropertyChanged 
{ 
    private string _name = ""; 
    public string Name 
    { 
     get { return _name; } 
     set { _name = value; OnPropertyChanged(); } 
    } 

    private bool _hasRead = false; 
    public bool HasRead 
    { 
     get { return _hasRead; } 
     set { _hasRead = value; OnPropertyChanged(); } 
    } 

    private Command _toggleRead; 
    public Command ToggleReadCommand  
    { 
     get 
     { 
      return _toggleRead 
       ?? (_toggleRead = new Command(() => HasRead = !HasRead)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 
public class StoriesViewModel : INotifyPropertyChanged 
{ 
    public StoriesViewModel() 
    { 
     // add sample stories 
     Stories.Add(new StoryViewModel { Name = "First Story" }); 
     Stories.Add(new StoryViewModel { Name = "Second Story", HasRead=true }); 
    } 

    private ObservableCollection<StoryViewModel> _stories = new ObservableCollection<StoryViewModel>(); 
    public ObservableCollection<StoryViewModel> Stories 
    { 
     get { return _stories; } 
     set { _stories = value; OnPropertyChanged(); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class StoryReadBackgroundColorConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (!(value is bool)) return null; 

     return (bool)value ? Color.FromRgba(0, 0, 0, 0.6) : Color.FromRgba(0, 0, 0, 0.0); 
    } 

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

是的,我把它綁定到我的viewmodel上,瞧!像魅力一樣工作。有點令人困惑,因爲它很奇怪,佈局是在ViewCell中分配的,但在更新視圖模型時會發生變化。不過,我採取了類似的方法,所以我標記了你的答案:) – jdmdevdotnet