wpf 如何将视图模型中的属性绑定到Label.Content within a dictionary.xaml

6fe3ivhb  于 2022-12-05  发布在  其他
关注(0)|答案(1)|浏览(250)

我有WPF MVVM应用程序。
我有一个WPF字典。xaml在其中我有以下样式:

<Style x:Key="myPopupStyle" TargetType="{x:Type ContentControl}">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <Border>
                    <Grid>
                        <Path x:Name="Container"
                              Data="M8,7.41 L15.415,0 L22.83,7.41 L224,7.41 L224,130 L0,130 L0,7.41 L8,7.41"
                              Fill="White"
                              Stroke="#BEBEBE">
                        </Path>
                        <StackPanel>
                            <Label Content="{Binding Path=myText, Mode=OneWay}"/>
                            <TextBlock Margin="5,10,5,5"
                                       MaxHeight="130"
                                       MaxWidth="224"
                                       Text="{TemplateBinding Content}"
                                       TextWrapping="Wrap" />
                        </StackPanel>
                    </Grid>
                </Border>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

然后在我的一个视图中,导入dictionary.xaml,并在弹出窗口中设置如下样式:
My View(我的视图.xaml):

<Window x:Class="my.UI.Views.myView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:vm="clr-namespace:my.UI.ViewModels"
             xmlns:v="clr-namespace:my.UI"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800">
    <Window.Resources>
        <ResourceDictionary>
            <!-- Dictionaries -->
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/myApps;component/Resources/Dictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

            <!-- SOME STUFF -->
            <Label x:Name="StatusText" Content="Hello!"/>
            <Popup AllowsTransparency="True"
                   PlacementTarget="{Binding ElementName=StatusText}"
                   Placement="Bottom">
                <ContentControl Content="{Binding Path=myTooltip, Mode=OneWay}" Style="{StaticResource myPopupStyle}"/>
            <Popup>

            <!-- MORE STUFF --->

</Window>

我的视图模型(myViewModel.cs)-仅显示此帖子的相关部分-:

public class myViewModel : ViewModelBase
{
    public myViewModel()
    {}

    public string myText
    {
            get => this._myText;

            set
            {
                if (this._myText!= value)
                {
                    this._myText= value;
                    this.OnPropertyChanged();
                }
            }
    }

    public string myTooltip
    {
            get => this._myTooltip;

            set
            {
                if (this._myTooltip!= value)
                {
                    this._myTooltip= value;
                    this.OnPropertyChanged();
                }
            }
    }

    public string _myText;
    public string _myTooltip;
}

在我的视图模型中,我有一个名为myText的属性,我将它绑定到dictionary. xaml中定义的样式中的Label。
当我运行它时,它不工作,抛出以下错误:
分派程序处理已挂起,但仍在处理消息。

************异常文本************系统.操作无效异常:已挂起调度程序处理,但仍在处理消息。at System.Windows.Threading.Dispatcher.WndProcHook在MS.Win32.HwndWrapper.WndProc中的(内部指针硬件、内部32消息、内部指针wParam、内部指针lParam、布尔值和已处理的)(内部指针硬件、内部32消息、内部指针w参数、内部指针l参数、在MS.Win32.HwndSubclass.DispatcherCallbackOperation中处理的布尔值(& T)(对象o)位于System.Windows.线程.ExceptionWrapper.InternalRealCall(委托回调,对象参数,Int 32 numArgs)位于System.Windows.线程.ExceptionWrapper.TryCatchWhen(对象源,委托回调,对象参数,Int 32 numArgs,委托捕获处理程序)

那么,如何将视图模型中的属性myText绑定到dictionary.xaml中样式中定义的Label呢?

hgc7kmma

hgc7kmma1#

1.我试图在我的评论中解释你在Popup内部的绑定是错误的。ContentControl.Content当前绑定到myViewModel.myTooltip,这是一个string
然后,ContententControl.ContentTemplate被设置为指向错误数据类型(myViewModel)的DataTemplate。每个绑定的实际数据类型是stringmyTolltip值)。
换句话说,DataTemplateContententControl.ContentTemplate)的DataContext是指派给ContententControl.Content属性的对象。
若要修正您的问题,ContentControl.Content必须指涉myViewModel执行严修(目前的DataContext)。您也可以将另一个TextBlock新增至DataTemplate,以显示myTooltip值:

<Popup>
  
  <!-- Assign the myViewModel to the Content property,
       so that the type of the DataTemplate matches the Content -->
  <ContentControl Content="{Binding}" 
                  Style="{StaticResource myPopupStyle}">
    <ContentControl.ContentTemplate>
      <DataTemplate DataType="{x:Type myViewModel}">
        <Border>
          <Grid>
            <Path />

            <StackPanel>
              <TextBlock Text="{Binding myText}" />
              <TextBlock Text="{Binding myTolltip}" />
            </StackPanel>
          </Grid>
        </Border>
      </DataTemplate>
    </ContentControl.ContentTemplate>
  </ContentControl>
</Popup>
  1. BindingMode.OneWay是默认值。显式设置此模式是多余的。
    1.字段不应为public。建议您改用属性。定义属性public的支持字段将允许绕过该属性,这可能会导致意外的副作用。唯一的例外是事件字段。编译器会对它们进行特殊处理(例如,编译器将创建属性并防止公共调用)
    1.不应将string绑定到Label.Content属性,因为这会导致性能下降。由于string是不可变的,因此更改Label.Content值(源string)将强制Label从头重建内容(例如,应用一个全新的模板),而不是更新内容。
    您应该更喜欢TextBlock,它经过优化可以更高效地处理string

相关问题