我如何传递一个引用到另一个控件作为的IValueConverter参数? [英] How can I pass a reference to another control as an IValueConverter parameter?

查看:683
本文介绍了我如何传递一个引用到另一个控件作为的IValueConverter参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我绑定了一些业务对象以一个WPF ItemsControl的。它们显示使用用于产生几何在DataTemplate中Path对象的自定义的IValueConverter实现,如下所示:

I am binding some business objects to a WPF ItemsControl. They are displayed using a custom IValueConverter implementation used to produce the Geometry for a Path object in the DataTemplate as shown here:

<ItemsControl x:Name="Display" 
              Background="White"
              HorizontalAlignment="Stretch" 
              VerticalAlignment="Stretch"
              ItemsSource="{Binding ElementName=ViewPlaneSelector, 
                                    Path=SelectedItem.VisibleElements}" 
           >
    <ItemsControl.Resources>
        <!-- This object is just used to get around the fact that ConverterParameter 
        can't be a binding directly (it's not a DependencyProperty on a DependencyObject -->
        <this:GeometryConverterData 
            x:Key="ConverterParameter2"
            Plane="{Binding ElementName=ViewPlaneSelector, 
                            Path=SelectedItem}" />
        <DataTemplate DataType="{x:Type o:SlenderMember}">
            <Path Stroke="Blue" StrokeThickness=".5"
              Data='{Binding Converter={StaticResource SlenderMemberConverter}, 
                            ConverterParameter={StaticResource ConverterParameter2}}'
              ToolTip="{Binding AsString}">
            </Path>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

请注意,该项目为ItemsControl的从ViewPlaneSelector(组合框)SelectedItem.VisibleElements属性绘制。我需要同V​​iewPlaneSelector.SelectedItem在SlenderMemberConverter弄清楚如何显示这个元素。我试图通过创建在参考资料部分中间GeometryConverterData对象来获取对它的引用到转换器。此对象存在仅得到解决不能够直接绑定到ConverterParameter属性(如上文中的评论)的问题。这里是code为GeometryDataConverter类:

Note that the items for the ItemsControl are drawn from the ViewPlaneSelector (a ComboBox) SelectedItem.VisibleElements property. I need that same ViewPlaneSelector.SelectedItem in the SlenderMemberConverter to figure out how to display this element. I'm trying to get a reference to it into the converter by creating the intermediate GeometryConverterData object in the Resources section. This object exists solely to get around the problem of not being able to bind directly to the ConverterParameter property (as mentioned in the comments). Here is the code for the GeometryDataConverter class:

class GeometryConverterData : FrameworkElement {
    public static readonly DependencyProperty PlaneProperty =
        DependencyProperty.Register("Plane", typeof(ViewPlane), 
            typeof(GeometryConverterData), null, ValidValue);

    public static bool ValidValue(object o){
        return true;
    }

    public ViewPlane Plane {
        get{
            return GetValue(PlaneProperty) as ViewPlane;
        }set{
            SetValue(PlaneProperty, value);
        }
    }
}

我添加了ValidValue功能进行调试,看看这个属性是得到约束它。它只是始终被设置为null。我知道ViewPlaneSelector.SelectedItem并非总是空,因为ItemsControl中有项目,它的项目是从同一个属性的同一对象上绘制...所以怎么办?我怎样才能得到一个参考这个组合框进我ValueConverter。

I added the ValidValue function for debugging, to see what this property was getting bound it. It only and always gets set to null. I know that the ViewPlaneSelector.SelectedItem isn't always null since the ItemsControl has items, and it's items are drawn from the same property on the same object... so what gives? How can I get a reference to this ComboBox into my ValueConverter.

或者交替,这是为什么我在做什么愚蠢的,过于复杂。我一样有罪很多,有时得到它在我脑海的东西已经被做了某种方式,然后杀死自己,使之发生时,有一个更清晰,更简单的解决方案。

Or, alternately, why is what I'm doing silly and overly complicated. I'm as guilty as many of sometimes getting it into my head that something has to be done a certain way and then killing myself to make it happen when there's a much cleaner and simpler solution.

推荐答案

抱歉,你就错了。

您整个论坛发帖是code气味层出不穷。
1.您使用值转换器转换成一个商业实体,它的视觉对口。这是在我的书code气味。
2.您正在寻找进入发送一个UI控件到业务逻辑。
3.诚实的上帝,这里有人说MultiBindings(外是正确的)我的头内爆和目前存在的虚无在我的脑子曾经是一个黑洞。

Your entire forum post is one code smell after another.
1. You're using Value Converters to convert a business entity to it's visual counterpart. That's a code smell in my book.
2. You're looking into sending a UI control to business logic.
3. Honest to god, someone here said "MultiBindings" (and beyond being right) my head imploded and there is now a black hole of nothingness where my brain used to be.

更多关于我的关于价值转换宗教信仰,触发器,MultiBindings等最差实践现实世界的LOB发展 - 随意读取的 WPF弟子的。

For more on my religious convictions regarding Value Converters, Trigger, MultiBindings and other worst practices for real-world LOB development - feel free to read the following thread on WPF Disciples.

不过,让我们专注于让你解开。 你需要一个 - 的视图模型的。

However, Let's focus on getting you untangled. You need a - ViewModel.

下面是你需要把该视图模型里面:
1.控制不相互结合。这是一个令人深恶痛绝,因为圣经时代看不见。每当财产以后在控制变化(ComboBox.SelectedItem,TextBox.Text,等等)绑定直接到视图模型。而不是结合PlaneSelector.SelectedItem和PlaneSelector.SelectedItem.VisibleElements于是,则selectedItem绑定回视图模型。
2.您的业务数据和correponding视觉重presentation在视图模型之间的转换。因此,有观点模型返回几何数据。

Here's what you need to put inside that ViewModel:
1. Controls don't bind to each other. It's an abomination unseen since biblical times. Whenever somthing on a control changes (ComboBox.SelectedItem, TextBox.Text, whatever) bind that directly to a ViewModel. So, instead of binding to PlaneSelector.SelectedItem and PlaneSelector.SelectedItem.VisibleElements, bind the selectedItem back to the ViewModel.
2. Convert between your business data and your correponding visual representation in the ViewModel. So, have the view model return the geometric data.

下面是一个粗略的草稿怎么一个超级简单的视图模型,它看起来像:

Here's a rough draft of how a super simple ViewModel that does that look like:

public class myFormViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void InvokePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler changed = PropertyChanged;
        if (changed != null) changed(this, new PropertyChangedEventArgs(propertyName));
    }


    private object _planeSelectedItem;
    public object PlaneSelectedItem
    {
        get { return _planeSelectedItem; }
        set
        {
            _planeSelectedItem = value;
            InvokePropertyChanged("PlaneSelectedItem");
        }
    }

    public IEnumerable<KeyValuePair<string, Geometry>> VisibleElements
    {
        get
        { 
           foreach(var slenderMember in PlaneSelectedItem.VisibleElements)
            {
                yield return new KeyValuePair<string, Geometry>(slenderMember.AsString, ToGeometry(slenderMember));
            }
        }
    }
}

而这里的大概你无法控制的那部分应该怎么是这样的:

And here's roughly how that part of your control should look like:

<ComboBox SelectedItem="{Binding PlaneSelectedItem, Mode=TwoWay}" />
<ItemsControl x:Name="Display" 
      Background="White"
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Stretch"
      ItemsSource="{Binding VisibleElements}">
    <ItemsControl.ItemTemplate>
        <DataTemplate >
            <Path Stroke="Blue" StrokeThickness=".5"
                  Data="{Binding Value}" ToolTip="{Binding Key}">
            </Path>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

显然,有一些失踪的$ C $这里C(设定this.DataContent =新myFormViewModel(),使用KeyValuePairs,设置组合框的ItemsSource等)。但这里的核心是简化这些疯狂的结合把戏。

Obviously, there's some missing code here (Setting the this.DataContent = new myFormViewModel(), using KeyValuePairs, setting the ComboBox ItemsSource, etc). But the core here is to simplify these crazy binding shenanigans.

- 只使用code。 它会让你的生活更简单。

Instead of trying to hack togather XAML to behave like code - just use code. It'll make your life much simpler.

这篇关于我如何传递一个引用到另一个控件作为的IValueConverter参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆