1

在我的视图模型(VM)中,我有一个 ObservableCollection 项目。在我看来,我绑定到集合。我创建了一些用户控件,它们具有我绑定到的依赖属性,称为 STCode。因此,例如,“标签”对象将具有字符串类型的“名称”属性和整数类型的“值”属性。

在我的视图模型中

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 value 属性(显示“Tag1”值)。无论如何,我可以通过指定字符串 Name 属性从 observableCollection 获取特定的“标签”对象吗?因此,基本上,如果我在视图中有 3 个用户控件实例,则在每个控件上,我想将标记对象的“名称”属性指定为 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));
        }
    }    
}
4

2 回答 2

1

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

[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 中添加值转换器。

于 2013-08-15T08:14:59.293 回答
1

由于您的用户控件绑定到集合本身而不是集合上的项目(转换器在内部完成此工作),因此当您想要刷新用户控件上的绑定时,您必须在整个集合上调用 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));
    }
}
于 2013-08-15T08:09:50.943 回答