c# - 从 ViewModel 到 Custom-Control 到 ControlTemplate 上的控件的多阶段绑定(bind)不起作用

标签 c# .net wpf xaml mvvm

我有一个 MVVM 项目,其 DataContext 中有一个 View 和一个 ViewModel .

在这个项目中,我有一个类 ComboBoxCustom它继承自 ComboBox 。我在 ComboBoxCustom 中定义了一些附加功能类。

至此ComboBoxCustom类我指定一个控件模板来定义其外观。

定义(简化)控件模板的(简化)样式如下所示:

<Style TargetType="{x:Type lib:ComboBoxCustom}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type lib:ComboBoxCustom}">
                <StackPanel>
                    <TextBlock Text="{TemplateBinding TextPropertyInComboBoxCustom}"/>

                    <ComboBox   DataContext="{TemplateBinding DataContext}" 
                                ItemsSource="{TemplateBinding ItemsSource}"
                                DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
                                SelectedValuePath="{TemplateBinding SelectedValuePath}"
                                SelectedValue="{TemplateBinding SelectedValue}" 
                                SelectedItem="{TemplateBinding SelectedItem}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

位于 ResourceDictionary 。真正的控制模板有一些附加功能,由于它们与问题无关,因此被省略。

我用这个ComboBoxCustom在我的 View 中控制使用:

<lib:ComboBoxCustom ItemsSource="{Binding MyObservableCollectionOfMyObjects}"
                     TextPropertyInComboBoxCustom="MyText"
                     DisplayMemberPath="MyDescription"
                     SelectedValuePath="MyValue"
                     SelectedItem="{Binding SelectedMyObject, Mode=TwoWay}"/>

View 正常,所有项目都加载到我可以选择的组合框中。

问题是,当我在组合框中选择不同的项目时,属性 SelectedMyObject我的 ViewModel 中没有更新,因此它的 setter 没有被调用。因此,有关所选对象的(正确)信息在我的 ViewModel 中不可用。

当我使用<ComboBox .../>时(没有 TextPropertyInComboBoxCustom 属性)而不是 <lib:ComboBoxCustom .../>一切工作正常,但我没有 ComboBoxMessage 中定义的附加功能我需要的。

任何人都可以告诉我出了什么问题以及如何解决此问题,以便我可以使用 ComboBoxMessage在我看来?最好不破坏 MVVM 模式。

谢谢!

最佳答案

感谢 ASh 在 this post 中的评论和信息.

问题是 TemplateBinding 是一种方法。因此,来自 ViewModel 的所有信息都可以进入模板中的控件。但反之则不然。

解决方案是将普通绑定(bind)指定为:

SelectedItem ="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"

它的功能与 TemplateBinding 大致相同,但有两种方式。

控件模板变成:

<Style TargetType="{x:Type lib:ComboBoxCustom}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type lib:ComboBoxCustom}">
                <StackPanel>
                    <TextBlock Text="{TemplateBinding TextPropertyInComboBoxCustom}"/>

                    <ComboBox   DataContext="{TemplateBinding DataContext}" 
                                ItemsSource="{TemplateBinding ItemsSource}"
                                DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
                                SelectedValuePath="{TemplateBinding SelectedValuePath}"
                                SelectedValue="{TemplateBinding SelectedValue}" 
                                SelectedItem ="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

但我不确定 SelectedValue 属性。对于这样的模板,当我使用 SelectedValue 属性或 SelectedItem 属性时,它都可以工作。

可以在 View 中省略 Mode=TwoWay 选项,因为 SelectedItem 的默认绑定(bind)模式已经是两种方式。 View 线变为:

<lib:ComboBoxCustom ItemsSource="{Binding MyObservableCollectionOfMyObjects}"
                    TextPropertyInComboBoxCustom="MyText"
                    DisplayMemberPath="MyDescription"
                    SelectedValuePath="MyValue"
                    SelectedItem="{Binding SelectedMyObject}"/>

关于c# - 从 ViewModel 到 Custom-Control 到 ControlTemplate 上的控件的多阶段绑定(bind)不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42835295/

相关文章:

c# - 检查 Uppercase 函数是否有效

c# - 是否可以使用 RabbitMQ 和 gRPC 通过 .NET 对消息进行排队?

.net - 是否可以用使用不同 key 签名的程序集来替换强名称程序集?

asp.net - 将列添加到新的 DataRow

c# - ASP.NET 自定义 404 返回 200 OK 而不是 404 Not Found

c# - 将文件复制到窗口应用程序中的文件夹中

c# - 尝试生成 xsd :schema using xsd. exe 时出错

c# - 在 WPF 应用程序中嵌入 Youtube 视频

javascript - WebBrowser 控件不适用于某些 javascript 结构

c# - 在哪些情况下我必须在 WPF 中序列化命令的对象?