2011-04-08 70 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

相关问题