通过检查string属性的值绑定到ObservableCollection中的某个项目

时间:2013-08-15 06:44:00

标签: wpf binding

在我的视图模型(VM)中,我有一个ObservableCollection项。在我看来,我对该集合具有约束力。我创建了一些用户控件,它们具有我绑定到名为STCode的依赖项属性。因此,例如,“Tag”对象将具有String类型的“Name”属性和integer类型的“value”属性。

在我的ViewModel

Constructor
Tags.Add(new Tag("Tag1",111));
Tags.Add(new Tag("Tag2",222));
Tags.Add(new Tag("Tag3",333));
Tags.Add(new Tag("Tag4",444));

public ObservableCollection<Tag> Tags
 {
     get
     {
         return _TagList;
     }
     set
     {
         if (value != _TagList)
         {
             _TagList = value;
         }
     }
 } 

在我的视图中

<my:UserControl1 x:Name="control1" Margin="12,89,0,0" HorizontalAlignment="Left" Width="257" Height="249" VerticalAlignment="Top" STCode="{Binding Path=Value}"/>

这将绑定到ObservableCollection中的First items值属性(显示“Tag1”值)。无论如何我可以通过指定字符串Name属性从observableCollection获取特定的“tag”对象吗?所以基本上如果我在视图中有3个usercontrol实例,在每个控件上我想将Tag对象的“Name”属性指定为XAML中的字符串,并且返回将该特定控件绑定到该特定标签整数“价值“财产?

我希望这是有道理的

模型

public class Tag : ModelBase
{
    private int _value;
    public string Tagname { get; set; }
    public int Value
    {
        get
        {
           return _value;
        }
        set
        {
            _value = value;
            NotifyPropertyChanged("Value");
        }
    }
}

模型库

public class ModelBase :INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }    
}

2 个答案:

答案 0 :(得分:0)

由于您的UserControls绑定到Collection本身而不是集合上的Item(转换器在内部执行此作业),因此当您要刷新用户控件上的绑定时,必须在整个Collection上调用PropertyChanged。

编辑:完整解决方案

视图模型:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Tag> Tags { get; private set; }

    public MainWindowViewModel()
    {
        Tags = new ObservableCollection<Tag>();
        Tags.Add(new Tag("Tag1", 111));
        Tags.Add(new Tag("Tag2", 222));
        Tags.Add(new Tag("Tag3", 333));
        Tags.Add(new Tag("Tag4", 444));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    public void ChangeRandomTag()
    {
        var rand = new Random();

        var tag = Tags[rand.Next(0, Tags.Count - 1)];

        tag.Value = rand.Next(0, 1000);

        OnPropertyChanged("Tags");
    }
}

查看XAML:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wpfApplication1="clr-namespace:WpfApplication1"
    Title="MainWindow"
    Width="525"
    Height="350">

<Window.Resources>
    <wpfApplication1:MyConverter x:Key="MyConverter" />
</Window.Resources>

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <ListBox ItemsSource="{Binding Tags}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Border Margin="1"
                        BorderBrush="Black"
                        BorderThickness="1"
                        CornerRadius="2">
                    <StackPanel Orientation="Vertical">
                        <TextBlock Text="{Binding Name}" />
                        <TextBlock Text="{Binding Value}" />
                    </StackPanel>
                </Border>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <StackPanel Grid.Column="1" Orientation="Vertical">
        <Button x:Name="buttonChangeRandomTag"
                Click="ButtonChangeRandomTag_OnClick"
                Content="Change Random Tag Value" />
        <TextBlock Text="{Binding Tags, Converter={StaticResource MyConverter}, ConverterParameter=Tag1}" />
        <TextBlock Text="{Binding Tags, Converter={StaticResource MyConverter}, ConverterParameter=Tag2}" />
        <TextBlock Text="{Binding Tags, Converter={StaticResource MyConverter}, ConverterParameter=Tag3}" />
        <TextBlock Text="{Binding Tags, Converter={StaticResource MyConverter}, ConverterParameter=Tag4}" />
    </StackPanel>

</Grid>

查看背后的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        DataContext = new MainWindowViewModel();
        InitializeComponent();
    }

    private void ButtonChangeRandomTag_OnClick(object sender, RoutedEventArgs e)
    {
        (DataContext as MainWindowViewModel).ChangeRandomTag();
    }
}

转换器:

[ValueConversion(typeof(ObservableCollection<Tag>), typeof(int))]
public class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var collection = value as ObservableCollection<Tag>;
        var key = parameter as string;

        if (collection == null || parameter == null)
            return 0;

        var result = collection.FirstOrDefault(item => item.Name.Equals(key));
        if (result == null)
            return 0;

        return result.Value;
    }

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

标签类:

public class Tag : INotifyPropertyChanged
{
    private string name;
    private int value;

    public string Name
    {
        get { return name; }
        set
        {
            if (value == name) return;
            name = value;
            OnPropertyChanged("Name");
        }
    }

    public int Value
    {
        get { return value; }
        set
        {
            if (value == this.value) return;
            this.value = value;
            OnPropertyChanged("Value");
        }
    }

    public Tag(string name, int value)
    {
        Value = value;
        Name = name;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

答案 1 :(得分:0)

您可以使用ValueConverter为您执行此操作:

[ValueConversion(typeof(string), typeof(string))]
public class StringToTagPropertyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value != typeof(ObservableCollection<Tag>)) return 
DependencyProperty.UnsetValue;
        if (parameter as string == null) return DependencyProperty.UnsetValue;
        ObservableCollection<Tag> tagObject = (ObservableCollection<Tag>)value;
        string returnValue = tagObject.Where(t => t.Name.ToLower() == 
parameter.ToString().ToLower()).FirstOrDefault();
        return returnValue ?? DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return DependencyProperty.UnsetValue; 
    }
}

您可以这样使用它:

<my:UserControl1 x:Name="control1" Margin="12,89,0,0" HorizontalAlignment="Left" 
Width="257" Height="249" VerticalAlignment="Top" STCode="{Binding Tags, 
Converter={StaticResource StringToTagPropertyConverter}, 
ConverterParameter="Name"}" />

通过更改ConverterParameter的值,您可以让ValueConverter返回“标记对象”的不同属性。我假设您知道如何在XAML中添加值转换器。