【问题标题】:Create a binding from a viewmodel collection class to a property in the datacontext创建从视图模型集合类到数据上下文中属性的绑定
【发布时间】:2020-08-07 14:52:35
【问题描述】:

我有一个带有多个计数器的视图模型,这些计数器用于 serval 方法。 在视图模型中,还有一个类 MenuItem 的集合,其中包含在功能区中创建动态菜单项的信息。在其中一些菜单项上,我想通过徽章显示计数器。

但要做到这一点,我需要将徽章绑定到计数器属性。 在我的 menuitem 类中,我有绑定的路径,但是我怎样才能让我的 menuitem 模板绑定到它自己绑定中的路径。

例子被简化了

public class ViewmodelSample
{
    public int counter1 { get; set; }

    public ICollection<MenuItem> MenuItems { get; set; } = new ObservableCollection<MenuItem>();

    public void Sample()
    {
        MenuItems.Add(new MenuItem()
        {
            Name = "Test button",
            CounterPath = "counter1"
        });
    }


    public class MenuItem
    {
        public string Name { get; set; }
        public string CounterPath { get; set; }
    }
}
<ItemsControl ItemsSource="{Binding Path=MenuItems}" >
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Name}"/>
                <TextBlock Text="{Binding Path={Binding CounterPAth}}"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

【问题讨论】:

  • MenuItem 类应该实现INotifyPropertyChanged 以触发Binding

标签: c# wpf mvvm data-binding


【解决方案1】:

您不能在Binding 标记扩展中绑定Path 属性,它不是DependencyProperty

您可以使用例如标识目标计数器Counter 类型为 int 的属性。将Style 应用到您的TextBlock,并使用触发器提供与ViewmodelSample 上相应计数器属性的绑定。您需要 RelativeSource 绑定,因为计数器位于父 DataContext 中。

<Style x:Name="CounterTextBlockStyle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type TextBlock}}">
   <Style.Triggers>
      <DataTrigger Binding="{Binding Counter}" Value="1">
         <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.counter1}"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding Counter}" Value="2">
         <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.counter2}"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding Counter}" Value="3">
         <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.counter3}"/>
      </DataTrigger>
   </Style.Triggers>
</Style>

【讨论】:

  • 这将是一个可行的解决方案,但我正在尝试获得更灵活的解决方案。
【解决方案2】:

现在我已经创建了一个助手类。 也许并不完美,但这对我有用(目前)。

助手类

    public class DynamicBindingHelper
{
    public string PropertyNaam { get; set; }



    public static string GetPath(DependencyObject obj)
    {
        return (string)obj.GetValue(PathProperty);
    }

    public static void SetPath(DependencyObject obj, string value)
    {
        obj.SetValue(PathProperty, value);
    }

    public static readonly DependencyProperty PathProperty =
        DependencyProperty.RegisterAttached("Path", typeof(string), typeof(DynamicBindingHelper), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnPathChanged)));


    private static void OnPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue == null || (e.NewValue is string val && val.IsNullOrWhiteSpace()))
            return;

        if (d == null)
            return;

        var binding = new Binding($"DataContext.{e.NewValue}")
        {
            RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(UserControl), 1),
            Mode=BindingMode.OneWay
        };

        switch (d)
        {
            case TextBlock _:
                BindingOperations.ClearBinding(d, TextBlock.TextProperty);
                BindingOperations.SetBinding(d, TextBlock.TextProperty, binding);
                break;
            case Badge _:
                BindingOperations.ClearBinding(d, Badge.ContentProperty);
                BindingOperations.SetBinding(d, Badge.ContentProperty, binding);
                break;
        }
    }
}

WPF 使用情况

<dx:Badge helper:DynamicBindingHelper.Path="{Binding TellerNaam}" Padding="2,2,2,3" FontSize="10" Margin="-3,5,3,-5" />

【讨论】:

    猜你喜欢
    • 2014-12-30
    • 2013-10-02
    • 2010-09-27
    • 2011-05-22
    • 2012-03-17
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多