求助:无法从共享方法引用类实例成员(XPO属性配置场景)
Hey there, let's break down what's going on here and fix that error!
First, the root cause of your "Cannot refer to an instance member of a class from a shared method" error: Attributes (like your ImageEditor attribute) are processed at compile time, which means their parameters can only be compile-time constants, static/shared members, or enum values. You can't directly reference an instance property like LogoWidth in an attribute parameter—since instance properties only exist when an object is created at runtime, the compiler can't resolve that value during compilation. If you tried to hack around this by referencing LogoWidth in a shared context, that's exactly what triggers the error you're seeing.
Now, here's the practical solution: use an XAF View Controller to dynamically set the Logo editor's width at runtime, based on the current object's LogoWidth value. This works because controllers run after your object instance is created, so you can access the LogoWidth property directly.
Solution 1: WinForms View Controller
Create a controller that targets your business class's DetailView, then update the PictureEdit's width whenever the current object changes or the LogoWidth property is modified:
Imports DevExpress.ExpressApp Imports DevExpress.ExpressApp.Win.Editors Imports DevExpress.XtraEditors.Controls Imports System.ComponentModel Public Class LogoWidthWinController Inherits ViewController(Of DetailView) Public Sub New() ' Replace "YourBusinessClass" with the actual name of your entity class TargetObjectType = GetType(YourBusinessClass) End Sub Protected Overrides Sub OnActivated() MyBase.OnActivated() ' Subscribe to object changes AddHandler View.CurrentObjectChanged, AddressOf OnCurrentObjectChanged If View.CurrentObject IsNot Nothing Then AddHandler CType(View.CurrentObject, INotifyPropertyChanged).PropertyChanged, AddressOf OnObjectPropertyChanged End If ' Set initial width UpdateLogoEditorWidth() End Sub Protected Overrides Sub OnDeactivated() ' Unsubscribe to avoid memory leaks RemoveHandler View.CurrentObjectChanged, AddressOf OnCurrentObjectChanged If View.CurrentObject IsNot Nothing Then RemoveHandler CType(View.CurrentObject, INotifyPropertyChanged).PropertyChanged, AddressOf OnObjectPropertyChanged End If MyBase.OnDeactivated() End Sub Private Sub OnCurrentObjectChanged(sender As Object, e As EventArgs) ' Re-subscribe to the new object's PropertyChanged event If View.CurrentObject IsNot Nothing Then AddHandler CType(View.CurrentObject, INotifyPropertyChanged).PropertyChanged, AddressOf OnObjectPropertyChanged End If UpdateLogoEditorWidth() End Sub Private Sub OnObjectPropertyChanged(sender As Object, e As PropertyChangedEventArgs) ' Update width only when LogoWidth changes If e.PropertyName = NameOf(YourBusinessClass.LogoWidth) Then UpdateLogoEditorWidth() End If End Sub Private Sub UpdateLogoEditorWidth() Dim logoEditor = View.FindItem("Logo") As ImagePropertyEditor If logoEditor IsNot Nothing AndAlso logoEditor.Control IsNot Nothing Then Dim pictureEdit = logoEditor.Control As DevExpress.XtraEditors.PictureEdit ' Set the width from the current object's LogoWidth property pictureEdit.Width = CType(View.CurrentObject, YourBusinessClass).LogoWidth ' Optional: Set size mode to stretch/fit the image to the new width pictureEdit.Properties.SizeMode = PictureSizeMode.Stretch End If End Sub End Class
Solution 2: Blazor View Controller
If you're working with XAF Blazor, the approach is similar but targets Blazor-specific editors:
Imports DevExpress.ExpressApp Imports DevExpress.ExpressApp.Blazor.Editors Imports System.ComponentModel Public Class LogoWidthBlazorController Inherits ViewController(Of DetailView) Public Sub New() TargetObjectType = GetType(YourBusinessClass) End Sub Protected Overrides Sub OnActivated() MyBase.OnActivated() AddHandler View.CurrentObjectChanged, AddressOf OnCurrentObjectChanged If View.CurrentObject IsNot Nothing Then AddHandler CType(View.CurrentObject, INotifyPropertyChanged).PropertyChanged, AddressOf OnObjectPropertyChanged End If UpdateLogoEditorWidth() End Sub Protected Overrides Sub OnDeactivated() RemoveHandler View.CurrentObjectChanged, AddressOf OnCurrentObjectChanged If View.CurrentObject IsNot Nothing Then RemoveHandler CType(View.CurrentObject, INotifyPropertyChanged).PropertyChanged, AddressOf OnObjectPropertyChanged End If MyBase.OnDeactivated() End Sub Private Sub OnCurrentObjectChanged(sender As Object, e As EventArgs) If View.CurrentObject IsNot Nothing Then AddHandler CType(View.CurrentObject, INotifyPropertyChanged).PropertyChanged, AddressOf OnObjectPropertyChanged End If UpdateLogoEditorWidth() End Sub Private Sub OnObjectPropertyChanged(sender As Object, e As PropertyChangedEventArgs) If e.PropertyName = NameOf(YourBusinessClass.LogoWidth) Then UpdateLogoEditorWidth() End If End Sub Private Sub UpdateLogoEditorWidth() Dim logoEditor = View.FindItem("Logo") As DxImagePropertyEditor If logoEditor IsNot Nothing Then ' Set width using CSS units (px, %, etc.) logoEditor.ComponentModel.Width = $"{CType(View.CurrentObject, YourBusinessClass).LogoWidth}px" End If End Sub End Class
Key Notes:
- Replace
YourBusinessClasswith the actual name of your entity class (the one containingLogoandLogoWidthproperties). - The
ImmediatePostDataattribute onLogoWidthensures that changes to the width are sent to the server immediately, which triggers ourPropertyChangedhandler to update the editor right away. - This approach avoids the compile-time restriction of attributes, since we're modifying the editor at runtime when the object instance is available.
内容的提问来源于stack exchange,提问作者Luk

