WPF游戏编辑器-更新UI/代码中的属性

本文关键字:代码 属性 UI 游戏 编辑器 更新 WPF | 更新日期: 2023-09-27 18:08:31

我试图在c#/WPF中创建一个游戏编辑器。编辑器包括一个显示场景的用户控件(在OpenGL中使用SharpGL渲染),以及许多用于编辑当前场景和对象的控件。对象由可以在编辑器中编辑属性的组件组成(类似于Unity游戏引擎)。我已经有了一个"组件编辑器"视图,它使用反射来查找组件上的所有属性,并为每个属性创建一个属性编辑器(例如,滑块)。但是,我不确定如何在UI和代码之间绑定属性。

问题是,我希望这些属性在代码中更改时在UI中更新,以及在UI中更改时在代码中更新。如果我想将编辑器控件(比如改变属性的滑块)绑定到组件属性上,它们必须实现NotifyPropertyChanged,这将非常麻烦。我想另一种方法是做脏检查,但我也不确定这是不是个好主意。

谁能给我指点这个属性更新之间的UI/代码应该如何处理?我希望它的工作原理很像Unity,在那里你不需要写任何额外的东西到你的组件类,使属性可编辑。

编辑:为了更清楚我想要实现的和已经拥有的,这里是"组件编辑器"用户控件的一部分。它的数据上下文是一个组件实例(模型)。PropertiesConverter返回它的属性(通过component.GetType(). getproperties())。ComponentPropertyTemplateSelector决定属性编辑器的用户控件(例如,对于双属性,它将选择具有用于编辑值的文本框的"数字编辑器")。我感兴趣的问题是如何将组件的属性双向绑定到编辑器控件。

<ItemsControl x:Name="ComponentProperties" Grid.Row="1" ItemTemplateSelector="{StaticResource ComponentPropertyTemplateSelector}">
    <ItemsControl.ItemsSource>
        <Binding Converter="{StaticResource PropertiesConverter}"/>
    </ItemsControl.ItemsSource>
</ItemsControl>

WPF游戏编辑器-更新UI/代码中的属性

我会说你可能想要遵循使用INotifyPropertyChanged接口的MVVM模式。如果你在谷歌上搜索MVVM,马上就会出现一些很好的文章。也有一些现有的工具可以帮助你开始。从你在问题中所描述的来看,MVVM模式本质上是这样工作的。它将UI和代码解耦,但仍然保持这种连接。真正快速的版本是在一个类上实现INotifyPropertyChanged,然后将该类的一个实例设置为想要为其设置绑定的控件的DataContext。可能更容易看到一个例子:

Xaml:

   <StackPanel>
        <Slider Value="{Binding SliderValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding MyText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox  Text="{Binding MyText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <Slider Value="{Binding SliderValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    </StackPanel>

我创建了一个视图模型库,以节省一些代码编写:

class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

视图模型类示例:

 class MyViewModel : ViewModelBase
    {
        private int sliderValue;
        private string myText;
        public int SliderValue
        {
            get { return this.sliderValue; }
            set
            {
                this.sliderValue = value;
                this.OnPropertyChanged();
            }
        }

        public string MyText
        {
            get { return this.myText; }
            set
            {
                this.myText = value;
                this.OnPropertyChanged();
            }
        }
    }

如何连接绑定(在本例中是控件后面的代码):

  public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MyViewModel();
        }

正如您所看到的,在设置视图模型和xaml中涉及到一些工作。与其他解决方案相比,我认为就你必须投入的"工作"数量而言,这是相当不错的。我不知道是否有任何方法可以绕过它,让它像"魔法"一样工作。也许有必要检查一下存在哪些MVVM工具,可能有一些东西可以使事情变得更简单。

您可以使用Castle动态代理(将类包装在代理中)或Fody(在构建后步骤中修改IL)自动添加IPropertyChangeNotification支持