如何将Foreground绑定到ViewModel中的属性?

时间:2011-04-08 22:39:52

标签: c# wpf mvvm

我想将TextBlock的foreground属性绑定到ViewModel中的Property。

这不起作用:

修改

查看:

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;
}

所有其他属性(文本等)正确绑定。

我做错了什么?

2 个答案:

答案 0 :(得分:21)

检查您的解决方案是否如此: 视图:

<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设置新值,你可以这样做:

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

提出PropertyChangedEvent

根据您的问题的新信息,您可以尝试这个解决方案:

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属性驻留在CustomerHeaderViewModel.cs中,因此它对所有客户都是值。在CustomerHeaderView.xaml中,我为UserControl添加了x:Name,以便有可能引用此元素的DataContext。如果您不想对UserControl使用x:Name,可以尝试:

<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

答案 1 :(得分:3)

将UI元素放入视图模型中不是一个好习惯。您的视图模型必须仅封装业务位置。

如果要更改UI中依赖于文本框值的任何内容的颜色,最好在XAML中使用数据触发器。

你可以这样做:

Viewmodel:

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”并且它返回一个Brush对象)

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