WPF 사용자 제어 상위 항목
사용자 컨트롤을 사용하여 로드할 수 있습니다.MainWindow
런타임에윈도우의 핸들을 잡을 수 없습니다.UserControl
.
난 시도했다.this.Parent
하지만 항상 null입니다.WPF의 사용자 컨트롤에서 포함된 창으로 핸들을 가져오는 방법을 아는 사람이 있습니까?
컨트롤이 로드되는 방법은 다음과 같습니다.
private void XMLLogViewer_MenuItem_Click(object sender, RoutedEventArgs e)
{
MenuItem application = sender as MenuItem;
string parameter = application.CommandParameter as string;
string controlName = parameter;
if (uxPanel.Children.Count == 0)
{
System.Runtime.Remoting.ObjectHandle instance = Activator.CreateInstance(Assembly.GetExecutingAssembly().FullName, controlName);
UserControl control = instance.Unwrap() as UserControl;
this.LoadControl(control);
}
}
private void LoadControl(UserControl control)
{
if (uxPanel.Children.Count > 0)
{
foreach (UIElement ctrl in uxPanel.Children)
{
if (ctrl.GetType() != control.GetType())
{
this.SetControl(control);
}
}
}
else
{
this.SetControl(control);
}
}
private void SetControl(UserControl control)
{
control.Width = uxPanel.Width;
control.Height = uxPanel.Height;
uxPanel.Children.Add(control);
}
다음을 사용해 보십시오.
Window parentWindow = Window.GetWindow(userControlReference);
그GetWindow
메소드가 Visual Tree를 걷고 컨트롤을 호스팅하는 창을 찾습니다.
이 코드는 컨트롤이 로드된 후에 실행해야 합니다(Windows 생성자가 아님).GetWindow
반품 방법null
예: 이벤트 연결:
this.Loaded += new RoutedEventHandler(UserControl_Loaded);
제 경험을 덧붙이겠습니다.Loaded 이벤트를 사용하면 작업을 수행할 수 있지만 OnInitialized 메서드를 재정의하는 것이 더 적합할 수 있습니다.로드는 윈도우가 처음 표시된 후에 발생합니다.초기화 시 창을 렌더링하기 전에 창에 컨트롤을 추가하는 등 변경할 수 있습니다.
Visual Tree Helper를 사용합니다.GetParent 또는 아래 재귀 함수를 사용하여 부모 창을 찾습니다.
public static Window FindParentWindow(DependencyObject child)
{
DependencyObject parent= VisualTreeHelper.GetParent(child);
//CHeck if this is the end of the tree
if (parent == null) return null;
Window parentWindow = parent as Window;
if (parentWindow != null)
{
return parentWindow;
}
else
{
//use recursion until it reaches a Window
return FindParentWindow(parent);
}
}
창을 사용해야 했습니다.Loaded 이벤트 처리기 내의 Window(이) 메서드를 가져옵니다.즉, Ian Oakes의 답변과 Alex의 답변을 함께 사용하여 사용자 컨트롤의 부모를 구했습니다.
public MainView()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainView_Loaded);
}
void MainView_Loaded(object sender, RoutedEventArgs e)
{
Window parentWindow = Window.GetWindow(this);
...
}
이 질문을 찾았지만 Visual Tree Helper가 작동하지 않거나 산발적으로 작동하지 않는 경우 알고리즘에 Logical Tree Helper를 포함해야 할 수 있습니다.
내가 사용하는 것은 다음과 같습니다.
public static T TryFindParent<T>(DependencyObject current) where T : class
{
DependencyObject parent = VisualTreeHelper.GetParent(current);
if( parent == null )
parent = LogicalTreeHelper.GetParent(current);
if( parent == null )
return null;
if( parent is T )
return parent as T;
else
return TryFindParent<T>(parent);
}
이 접근 방식은 저에게 효과가 있었지만 질문만큼 구체적이지는 않습니다.
App.Current.MainWindow
이거 어때:
DependencyObject parent = ExVisualTreeHelper.FindVisualParent<UserControl>(this);
public static class ExVisualTreeHelper
{
/// <summary>
/// Finds the visual parent.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sender">The sender.</param>
/// <returns></returns>
public static T FindVisualParent<T>(DependencyObject sender) where T : DependencyObject
{
if (sender == null)
{
return (null);
}
else if (VisualTreeHelper.GetParent(sender) is T)
{
return (VisualTreeHelper.GetParent(sender) as T);
}
else
{
DependencyObject parent = VisualTreeHelper.GetParent(sender);
return (FindVisualParent<T>(parent));
}
}
}
생성자에서 UserControl의 부모가 항상 null이지만 이벤트 핸들러에서 부모가 올바르게 설정되어 있습니다.제어 트리가 로드되는 방식과 관련이 있을 것 같습니다.이 문제를 해결하려면 로드된 컨트롤 이벤트에서 상위 항목을 가져올 수 있습니다.
예를 들어 이 질문을 확인하려면 WPF User Control의 DataContext가 Null입니다.
다른 방법:
var main = App.Current.MainWindow as MainWindow;
제게 효과가 있습니다.
DependencyObject GetTopLevelControl(DependencyObject control)
{
DependencyObject tmp = control;
DependencyObject parent = null;
while((tmp = VisualTreeHelper.GetParent(tmp)) != null)
{
parent = tmp;
}
return parent;
}
이는 트리를 너무 높게 설정하고 전체 애플리케이션에 대한 절대적인 루트 창을 제공했기 때문에 저에게는 효과가 없었습니다.
Window parentWindow = Window.GetWindow(userControlReference);
그러나 이것은 즉시 창을 얻는 데 효과적이었습니다.
DependencyObject parent = uiElement;
int avoidInfiniteLoop = 0;
while ((parent is Window)==false)
{
parent = VisualTreeHelper.GetParent(parent);
avoidInfiniteLoop++;
if (avoidInfiniteLoop == 1000)
{
// Something is wrong - we could not find the parent window.
break;
}
}
Window window = parent as Window;
window.DragMove();
창뿐만 아니라 트리 구조의 특정 부모를 가져오고 재귀 또는 하드 브레이크 루프 카운터를 사용하지 않으려면 다음을 사용할 수 있습니다.
public static T FindParent<T>(DependencyObject current)
where T : class
{
var dependency = current;
while((dependency = VisualTreeHelper.GetParent(dependency) ?? LogicalTreeHelper.GetParent(dependency)) != null
&& !(dependency is T)) { }
return dependency as T;
}
에 이 전화를 Parent
속성이 아직 초기화되지 않았습니다.로드 이벤트 핸들러 또는 응용 프로그램의 다른 부분에 추가합니다.
DependencyObject parent = ExVisualTreeHelper.FindVisualParent<UserControl>(this);
DependencyObject GetTopParent(DependencyObject current)
{
while (VisualTreeHelper.GetParent(current) != null)
{
current = VisualTreeHelper.GetParent(current);
}
return current;
}
DependencyObject parent = GetTopParent(thisUserControl);
그Window.GetWindow(userControl)
합니다. (으)로 표시됩니다.InitializeComponent()
메서드가 완료됨).
를 들어을 넣는 ) 즉, 사예된초경함우화기창(사용자 컨트롤: 파일에용사 xaml경우사자한용자컨의트롤삽컨을)에 표시됩니다.OnInitialized
이트창null얻못것할입다지니을다(사용자 컨트롤의 벤될것니입이null것),(다입)이기 에 창이 표시되지 ). 이 경우 사용자 컨트롤이OnInitialized
창이 초기화되기 전에 이벤트가 발생합니다.
이것은 또한 사용자 컨트롤이 창 이후에 초기화된 경우 사용자 컨트롤의 생성자에 이미 창을 가져올 수 있음을 의미합니다.
위의 금도금판 (나는 a를 추론할 수 있는 제네릭 함수가 필요합니다.Window
의맥안서의 에서.MarkupExtension
:-
public sealed class MyExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider) =>
new MyWrapper(ResolveRootObject(serviceProvider));
object ResolveRootObject(IServiceProvider serviceProvider) =>
GetService<IRootObjectProvider>(serviceProvider).RootObject;
}
class MyWrapper
{
object _rootObject;
Window OwnerWindow() => WindowFromRootObject(_rootObject);
static Window WindowFromRootObject(object root) =>
(root as Window) ?? VisualParent<Window>((DependencyObject)root);
static T VisualParent<T>(DependencyObject node) where T : class
{
if (node == null)
throw new InvalidOperationException("Could not locate a parent " + typeof(T).Name);
var target = node as T;
if (target != null)
return target;
return VisualParent<T>(VisualTreeHelper.GetParent(node));
}
}
MyWrapper.Owner()
추론합니다.
- 본근
Window
시각적 트리를 걸음으로써 (만약 의 맥락에서 사용된다면)UserControl
) - (경맥사서는우용되되에락의▁a▁within▁of▁context▁it()의 맥락에서 되는 경우)
Window
다른 접근 방식과 다른 전략.제 경우 VisualTreeHelper를 사용하거나 Telerik의 확장 메서드를 사용하여 지정된 유형의 부모를 찾을 수 없습니다.대신 애플리케이션을 사용하여 콘텐츠의 사용자 지정 주입을 허용하는 내 대화 뷰를 찾았습니다.현재의.창문들.
public Window GetCurrentWindowOfType<TWindowType>(){
return Application.Current.Windows.OfType<TWindowType>().FirstOrDefault() as Window;
}
언급URL : https://stackoverflow.com/questions/302839/wpf-user-control-parent
'programing' 카테고리의 다른 글
SQLAlchemy create_all()이 테이블을 생성하지 않습니다. (0) | 2023.05.06 |
---|---|
치명적: 사용자 "postgres"에 대한 암호 인증 실패(pgAdmin 4에서 postgresql 11 이후) (0) | 2023.05.06 |
iOS 프로젝트를 빌드하지 못했습니다."xcodebuild" 명령을 실행했지만 오류 코드 65와 함께 종료되었습니다. (0) | 2023.05.06 |
딜러를 사용해야 하는 시기와 이유는 무엇입니까? (0) | 2023.05.06 |
SQL Server에서 외부 키 종속성을 찾는 방법은 무엇입니까? (0) | 2023.05.06 |