2014-10-30 49 views
1

我是一個巨大的XAML noob,我正在用MVVM構建一個WinRT應用程序。基本上,我有一個函數getBackgroundColor(),它返回一個SolidColorBrush,我想讓它在任何給定的時間都可以改變背景顏色,並讓XAML元素注意並更改以匹配getBackgroundColor的新輸出。我知道這應該用綁定來完成,但並不真正瞭解任何在線文檔。有人能像我這樣向我解釋這個5嗎?如何在視圖在屏幕上時修改XAML元素的顏色?

回答

1

假設你知道屬性和接口是什麼 - 你需要一個屬性來綁定,所以例如你將有一個Border元素,其綁定設置爲Background={Binding BackgroundBrush}。然後,您將擁有一個實現了INotifyPropertyChanged接口的類型的視圖模型對象。該界面有一個事件 - PropertyChanged,並且當屬性值發生更改時需要引發該事件,因此最常見的情況是,「綁定」屬性將在其設置器中設置爲與以前值​​不同的值時引發該事件。您的視圖模型的代碼可能是這樣的,那麼:

public event PropertyChangedEventHandler PropertyChanged; 

private Brush _backgroundBrush; 
public Brush BackgroundBrush 
{ 
    get 
    { 
     return Brush _backgroundBrush; 
    } 
    set 
    { 
     if (_backgroundBrush == value) 
      return; 
     _backgroundBrush = value; 
     PropertyChanged(this, new PropertyCHangedEventArgs("BackgroundBrush"); 
    } 
} 

更常見的,雖然你可以創建一個基類有點像這樣:

abstract class BindableBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var eventHandler = this.PropertyChanged; 
     if (eventHandler != null) 
     { 
      eventHandler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) 
    { 
     if (object.Equals(storage, value)) 
     { 
      return false; 
     } 

     storage = value; 
     this.OnPropertyChanged(propertyName); 
     return true; 
    } 
} 

那麼你的視圖模型看起來是這樣的:

class MyViewModel : BindableBase 
{ 
    private Brush _backgroundBrush; 
    public Brush BackgroundBrush 
    { 
     get { return Brush _backgroundBrush; } 
     set { SetProperty(ref _backgroundBrush, value); } 
    } 
} 

這使得您的視圖模型更清晰和更安全重構(您不會傳遞屬性名稱)。

至於在視圖在屏幕上時修改XAML元素的顏色 - 有什麼意義?如果它的顏色只在屏幕上被修改 - 爲什麼不總是使用相同的顏色?此外,如果您正在編寫響應UI中的更改(如滾動)的任何代碼(通常最好是在視圖一側編寫該代碼),在控件,附加行爲或某種服務類中。

2

翻轉的答案是一個教科書的答案,並將很可能實現您正在尋找的結果。通常對於我來說,我發現MVVM是學術界和現實世界的不斷練習。 MVVM模式在您的場景中運行後,但還有其他方法可以更改UI顏色。這就是談話開始的地方。 ViewModel是否需要知道視圖如何顯示您顯示的內容?如果是的話,堅持另一個答案。如果不是,在拍攝視圖(你的window.xaml和window.xaml.cs)中拍一拍(你的window.xaml和window.xaml.cs)

例如,我有一個顏色轉換器我使用,因爲我決定我的ViewModel不需要知道我的顏色在視圖中切換。因此,在視圖xaml.cs(還是真的,因爲它是一個類,你可以聲明這在任何地方),我定義:

/// <summary> 
///  A way to convert the color of text based upon maintenance required 
/// </summary> 
public class MaintenenceColorConverter : IValueConverter 
{ 
    #region Properties 

    // Properties 
    public Color NormalColor { get; set; } 
    public Color NoMaintenanceRequiredColor { get; set; } 

    #endregion 

    /// <summary> 
    ///  DEFAULT CONSTRUCTOR 
    /// </summary> 
    public MaintenenceColorConverter() { } 

    /// <summary> 
    ///  Convert the color of the text based upon maintenance required 
    /// </summary> 
    /// <returns> 
    ///  The appropriate color property 
    /// </returns> 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 

     if (value.ToString() == "No Maintenance Required") return NoMaintenanceRequiredColor.ToString(); 

     return NormalColor.ToString(); 
    } 

    /// <summary> 
    ///  Not used: NECESSARY FOR IMPLEMENTATION 
    /// </summary> 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 

    } 

} 

現在,這是不漂亮,因爲我覺得我通過檢查那種違反MVVM設計模式在視圖模型的數據視圖中,但我沒關係(讓火焰開始!)。

所以在這一點,所有你需要在你的XAML做,然後是定義你的顏色轉換器:

<UserControl.Resources> 
     <localColor:MaintenenceColorConverter x:Key="MyColorConverter" NormalColor="Black" NoMaintenanceRequiredColor="Gray" /> 
    </UserControl.Resources> 

,然後用它在任何必要!我用它在一個數據網格「灰色」選擇:

   <DataGrid.Columns> 
       <DataGridTextColumn Header="Site Number" Binding="{Binding Path=SiteNo}" IsReadOnly="True" Width="100"> 
        <DataGridTextColumn.ElementStyle> 
         <Style TargetType="TextBlock"> 
          <Setter Property="HorizontalAlignment" Value="Center" /> 
          <Setter Property="Foreground" Value="{Binding Path=MaintStatus, Converter={StaticResource MyColorConverter}}" /> 
          <Setter Property="VerticalAlignment" Value="Center" /> 
         </Style> 
        </DataGridTextColumn.ElementStyle> 
       </DataGridTextColumn> 
       <DataGrid.Columns> 

乾杯!

+1

看起來很好,雖然我不確定從Color到Brush的隱式轉換是否可以在WinRT/XAML中工作(DataGrid必須是WPF,對嗎?)。從視圖中檢查視圖模型是非常好的,但是在代碼中比較字符串看起來並不是最佳實踐。在視圖模型方面使用'bool'或'enum'可能會更好。無論如何,有很多方法可以實現相同的目標。在虛擬機上使用Color或Brush屬性並不是最好的解決方案,但它可能是最簡單的。您也可以根據具體情況使用轉換器或VisualStateManager。 +1 – 2014-11-07 00:30:08

+1

我喜歡這個答案,但是當我嘗試實現它時失敗了,在ConvertBack對象上發生錯誤不會返回任何內容。建議? – Brady 2015-09-21 05:31:46

+0

對不起,這是一個黑客,但你可以返回「拋出新的NotImplementedException();」但理想情況下,您應該做與您在轉換方法中做的相反的事情。更多可以在[這裏]找到(https://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.convertback%28v=vs.110%29.aspx) – Stunna 2015-09-24 20:34:55

相關問題