2011-04-08 74 views
11

我想將TextBlock的前景屬性綁定到ViewModel中的屬性。如何將前景綁定到ViewModel中的屬性?

這不起作用:

編輯

查看:

TextBlock 
Text="{Binding Path=FullName, Mode=OneWay}" 
Foreground="{Binding Path=ForegroundColor}" 
Margin="0 5 3 5" 

後面的代碼:

CustomerHeaderViewModel customerHeaderViewModel = new CustomerHeaderViewModel(); 
customerHeaderViewModel.LoadCustomers(); 
CustomerHeaderView.DataContext = customerHeaderViewModel; 

視圖模型:

private System.Windows.Media.Brush _foregroundColor; 
_foregroundColor = System.Windows.Media.Brushes.DarkSeaGreen; 

public System.Windows.Media.Brush ForegroundColor 
{ 
    get { return _foregroundColor; } 
    set { _foregroundColor = value; 
     OnPropertyChanged("ForegroundColor"); 
    } 
} 

public CustomerHeaderViewModel() 
{ 
ForegroundColor = System.Windows.Media.Brushes.Red; 
} 

所有其他屬性(文本等)正確綁定。

我在做什麼錯?

+0

你在哪裏設置_foregroundColor?在虛擬機的ctor中? – 2011-04-08 23:58:22

回答

17

檢查您的解決方案是這樣的: 查看:

<Window x:Class="WpfApplication13.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:vm="clr-namespace:WpfApplication13" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <vm:MainVM/> 
    </Window.DataContext> 
    <Grid> 
     <TextBlock Text="{Binding Path=FullName, Mode=OneWay}" 
        Foreground="{Binding Path=ForegroundColor}" 
        Margin="0 5 3 5"/> 
    </Grid> 
</Window> 

視圖模型:

public class MainVM : INotifyPropertyChanged 
{ 
    protected void OnPropertyChanged(string porpName) 
    { 
     var temp = PropertyChanged; 
     if (temp != null) 
      temp(this, new PropertyChangedEventArgs(porpName)); 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 

    private System.Windows.Media.Brush _foregroundColor = System.Windows.Media.Brushes.DarkSeaGreen; 

    public string FullName 
    { 
     get 
     { 
      return "Hello world"; 
     } 
    } 

    public System.Windows.Media.Brush ForegroundColor 
    { 
     get { return _foregroundColor; } 
     set 
     { 
      _foregroundColor = value; 
      OnPropertyChanged("ForegroundColor"); 
     } 
    } 
} 

Running app

,記住,如果你想設置VM的ForegroundColor新價值你sholud這樣做:

ForegroundColor = System.Windows.Media.Brushes.Red; 

提高PropertyChangedEvent

Accordind到你的問題的新信息,你可以試試這個解決方案:

CustomerHeaderViewModel.cs

class CustomerHeaderViewModel : INotifyPropertyChanged 
{ 
    public ObservableCollection<Customer> Customers { get; set; } 

    public void LoadCustomers() 
    { 
     ObservableCollection<Customer> customers = new ObservableCollection<Customer>(); 

     //this is where you would actually call your service 
     customers.Add(new Customer { FirstName = "Jim", LastName = "Smith", NumberOfContracts = 23 }); 
     customers.Add(new Customer { FirstName = "Jane", LastName = "Smith", NumberOfContracts = 22 }); 
     customers.Add(new Customer { FirstName = "John", LastName = "Tester", NumberOfContracts = 33 }); 
     customers.Add(new Customer { FirstName = "Robert", LastName = "Smith", NumberOfContracts = 2 }); 
     customers.Add(new Customer { FirstName = "Hank", LastName = "Jobs", NumberOfContracts = 5 }); 

     Customers = customers; 
    } 
    protected void OnPropertyChanged(string porpName) 
    { 
     var temp = PropertyChanged; 
     if (temp != null) 
      temp(this, new PropertyChangedEventArgs(porpName)); 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 

    private System.Windows.Media.Brush _foregroundColor = System.Windows.Media.Brushes.DarkSeaGreen; 

    public System.Windows.Media.Brush ForegroundColor 
    { 
     get { return _foregroundColor; } 
     set 
     { 
      _foregroundColor = value; 
      OnPropertyChanged("ForegroundColor"); 
     } 
    } 
} 

CustomerHeaderView.xaml

<UserControl x:Class="TestMvvm444.Views.CustomerHeaderView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    x:Name="main"> 
    <Grid> 
     <StackPanel HorizontalAlignment="Left"> 
      <ItemsControl ItemsSource="{Binding Path=Customers}"> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <StackPanel Orientation="Horizontal"> 
          <StackPanel Orientation="Horizontal"> 
           <TextBox 
           Text="{Binding Path=FirstName, Mode=TwoWay}" 
           Width="100" 
           Margin="3 5 3 5"/> 
           <TextBox 
           Text="{Binding Path=LastName, Mode=TwoWay}" 
           Width="100" 
           Margin="0 5 3 5"/> 
           <TextBlock 
           Text="{Binding Path=FullName, Mode=OneWay}" 
           Foreground="{Binding ElementName=main, Path=DataContext.ForegroundColor}" 
           Margin="0 5 3 5"/> 
          </StackPanel> 
         </StackPanel> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 
     </StackPanel> 
    </Grid> 
</UserControl> 

在ForegroundColor屬性駐留在CustomerH中eaderViewModel.cs因此對所有客戶都是有價值的。在CustomerHeaderView.xaml中,我爲UserControl添加了x:Name,以便有可能引用此元素的DataContext。如果你不想用X:名稱爲用戶控件,你可以試試這個:

<TextBlock 
    Text="{Binding Path=FullName, Mode=OneWay}" 
    Foreground="{Binding RelativeSource={RelativeSource FindAncestor, 
    AncestorType={x:Type UserControl}}, Path=DataContext.ForegroundColor}" 
    Margin="0 5 3 5"/> 

記住,這種控制的DataContext在MainWindow.cs先前設置。

MainWindow.cs

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     CustomerHeaderViewModel customerHeaderViewModel = new CustomerHeaderViewModel(); 
     customerHeaderViewModel.LoadCustomers(); 
     CustomerHeaderView.DataContext = customerHeaderViewModel; 
    } 
} 

App

+0

非常感謝PawelSt,仍然遇到同樣的問題。我在上面添加了更多代碼。該文本塊位於用戶控件內,但正如前面提到的所有屬性加載正確 - 只是不ForelynColor ..謝謝 – 2011-04-09 08:01:26

+0

我不明白你的情況,什麼可能出錯,但嘗試將ForegroundColor類型從刷到SolidColorBrush。 – PawelSt 2011-04-09 08:20:48

+0

感謝PawelSt,前臺綁定不適用於我的應用,所以我回到基礎,下載並修改了Edward Tanguay的示例:http:更改TextBlock的Foreground屬性,希望能夠修復我的問題並將其轉移到我的應用程序的解決方案中。 – 2011-04-09 10:02:47

3

這不是把UI元素在您的視圖模型一個很好的做法。您的視圖模型只能封裝業務位置。

如果您想要改變UI中取決於文本框值的任何內容的顏色,最好在XAML中使用數據觸發器。

你可以這樣做:

視圖模型:

public class MainVm : INotifyPropertyChanged 
{ 
    protected void OnPropertyChanged(string porpName) 
    { 
     var temp = PropertyChanged; 
     if (temp != null) 
      temp(this, new PropertyChangedEventArgs(porpName)); 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 

    public string FullName 
    { 
     get { return "Hello world"; } 
    } 
} 

XAML(編輯使用顏色選擇器,假設他的控制選擇的值被命名爲「的SelectedValue」,它返回一個刷對象)

<Grid> 
    <TextBlock Text="{Binding Path=FullName, Mode=OneWay}" 
       Margin="0 5 3 5" Foreground="{Binding ElementName=colorpicker, Path=SelectedValue}"/> 
    <ColorPicker x:Name="colorpicker"/> 
</Grid> 
+0

感謝Bruno - 我使用顏色選擇器控件在視圖模型中設置ForegroundColor,因爲它可以是任何有效的十六進制數 - 因此我需要視圖模型中的邏輯,並且我不認爲在Setter中綁定被支持.. – 2011-04-09 09:40:38

+0

如果你可以綁定你的顏色選擇器的選定值到你的視圖模型,那麼你可以直接將你的文本框的Foreground屬性直接綁定到你的顏色選擇器:)我編輯了我的回覆給你一個例子。沒什麼更簡單的,不需要再使用你的viewmodel了!因此,每次用戶更改顏色選擇器中的值時,它都必須自動更新您的文本框前景,全部採用XAML綁定:) – Bruno 2011-04-09 11:56:55

+0

感謝您的時間和建議Bruno。我在我的應用程序中有幾個用戶控件,他們的視圖模型通過訂閱一個事件聚合器事件來更新,所以'Binding ElementName = colorpicker'將不起作用....那就是爲什麼我回到基礎只是爲了解決這個問題,通過下載並修改Edward Tanguay的示例:tanguay.info/web/index.php?pg=codeExamples&id=139更改TextBlock的Foreground屬性,希望能解決我的問題並將其轉移到我的應用程序的解決方案 – 2011-04-09 12:38:08

相關問題