Closed SAgiKPJH closed 9 months ago
<Window x:Class="Client.Presentation.UI.LoginView"
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"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
xmlns:common="clr-namespace:Client.Presentation.Common.DI"
xmlns:viewModels="clr-namespace:Client.Business;assembly=Client.Business"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
DataContext="{common:DISource Type={x:Type viewModels:LoginViewModel}}">
<Window.Resources>
<!--<BooleanToVisibilityConverter x:Key="BooleanToVisibility" /> --> <!-- IsLoaded = false -->
<dxmvvm:BooleanToVisibilityConverter x:Key="BooleanToVisibility" /> <!-- IsLoaded = true -->
</Window.Resources>
<Window.Visibility>
<Binding Path="IsViewVisible"
Mode="OneWay"
Converter="{StaticResource BooleanToVisibility}" />
</Window.Visibility>
<Grid Background="White">
</Grid>
</Window>
// LoginViewModel.cs
public class LoginViewModel : ViewModelBase
{
public bool IsViewVisible
{
get { return GetProperty(() => IsViewVisible); }
set { SetProperty(() => IsViewVisible, value); }
}
public LoginViewModel()
{
}
}
// App.xaml
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Services = ConfigureServices();
DISource.Resolver = Resolve;
var loginView = new LoginView();
loginView.Show();
loginView.IsVisibleChanged += (s, ev) =>
{
if (!loginView.IsVisible && loginView.IsLoaded) // in this point
{
var mainView = new MainWindow();
mainView.Show();
loginView.Close();
}
};
}
IsVisibleChanged
이벤트가 동작합니다.BooleanToVisibilityConverter
를 사용하면 loginView.IsLoaded = false
dxmvvm:BooleanToVisibilityConverter
를 사용하면 loginView.IsLoaded = true
(🔴오류 발생🔴)dxmvvm:BooleanToVisibilityConverter
의 코드 내용과 동일한 Converter를 Local에 구현해 사용하면 loginView.IsLoaded = false
오류 미발생합니다.dxmvvm:BooleanToVisibilityConverter
를 호출하는 과정에서 Window Loaded 이벤트와 관련된 기능이 있을 것으로 추측합니다.Hello I Have some ploblem
<Window x:Class="Client.Presentation.UI.LoginView"
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"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
xmlns:common="clr-namespace:Client.Presentation.Common.DI"
xmlns:viewModels="clr-namespace:Client.Business;assembly=Client.Business"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
DataContext="{common:DISource Type={x:Type viewModels:LoginViewModel}}">
<Window.Resources>
<!--<BooleanToVisibilityConverter x:Key="BooleanToVisibility" /> --> <!-- IsLoaded = false -->
<dxmvvm:BooleanToVisibilityConverter x:Key="BooleanToVisibility" /> <!-- IsLoaded = true -->
</Window.Resources>
<Window.Visibility>
<Binding Path="IsViewVisible"
Mode="OneWay"
Converter="{StaticResource BooleanToVisibility}" />
</Window.Visibility>
<Grid Background="White">
</Grid>
</Window>
// LoginViewModel.cs
public class LoginViewModel : ViewModelBase
{
public bool IsViewVisible
{
get { return GetProperty(() => IsViewVisible); }
set { SetProperty(() => IsViewVisible, value); }
}
public LoginViewModel()
{
}
}
// App.xaml
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Services = ConfigureServices();
DISource.Resolver = Resolve;
var loginView = new LoginView();
loginView.Show();
loginView.IsVisibleChanged += (s, ev) =>
{
if (!loginView.IsVisible && loginView.IsLoaded) // in this point
{
var mainView = new MainWindow();
mainView.Show();
loginView.Close();
}
};
}
When closing the window, the IsVisibleChanged
event is triggered.
Depending on whether you choose BooleanToVisibilityConverter
or dxmvvm:BooleanToVisibilityConverter
, the IsLoaded
part in the cs code of App.xaml
appears as either false
or true
.
This prevents me from using dxmvvm:BooleanToVisibilityConverter
.
I'm curious about the cause of this issue and a possible solution.
var loginView = new LoginView();
loginView.Show();
loginView.IsVisibleChanged += (s, ev) =>
{
if (!loginView.IsVisible && loginView.IsLoaded) // in this point
{
var mainView = new MainWindow();
mainView.Show();
loginView.Close();
}
};
위 코드를 사용하는 이유
ViewModel에서 Sinup에 성공할 시 Visiable = false 합니다.
이때, Visiable은 False가 되었으니, IsVisibleChanged 이벤트 동작합니다.
하지만 IsLoaded 값은 True 이기 때문에, MainView가 Show 됩니다.
일반적으로 창을 종료할 시 IsLoaded는 False됩니다.
결론적으로, SignUp 되었는지 안되었는지 구분하기 위해서 위 코드를 사용합니다.
또한 위 코드에서는 App.xaml에서 Signup에 따라 위 코드가 동작한 다는 사실을 알 수 없기에
옳바른 코드가 아니라 판단합니다.
Show()
가 아닌 DialogShow()
를 통해 종료될 때 까지 기다리고, return 값을 받는 것을 추천합니다. var loginView = new LoginView();
loginView.ShowDialog();
if (loginView.DialogResult == true)
{
var mainView = new MainWindow();
mainView.Show();
loginView.Close();
}
var loginView = new LoginView();
loginView.ShowDialog();
if (loginView.DialogResult == true && loginView.IsSignUp == true) // 또는 특정 변수 추가해서 관리
{
var mainView = new MainWindow();
mainView.Show();
loginView.Close();
}
I apologize for the inconvenience.
It seems that there is a problem when there is a Binding element inside the Grid. I accidentally omitted and deleted the XAML code.
If there is a Binding element as follows, there may be an issue with the use of dxmvvm:BooleanToVisibilityConverter
.
I share the file and video with you.
<Window.DataContext>
<common:LoginViewModel />
</Window.DataContext>
<Window.Resources>
<!--<BooleanToVisibilityConverter x:Key="BooleanToVisibility" />--> <!-- IsLoaded = false -->
<dxmvvm:BooleanToVisibilityConverter x:Key="BooleanToVisibility" /> <!-- IsLoaded = true -->
</Window.Resources>
<Window.Visibility>
<Binding Path="IsViewVisible"
Mode="OneWay"
Converter="{StaticResource BooleanToVisibility}" />
</Window.Visibility>
<Grid Background="White">
<TextBox Text="{Binding Id}" />
</Grid>
public class LoginViewModel : ViewModelBase
{
public string Id
{
get { return GetProperty(() => Id); }
set { SetProperty(() => Id, value); }
}
public bool IsViewVisible
{
get { return GetProperty(() => IsViewVisible); }
set { SetProperty(() => IsViewVisible, value); }
}
public LoginViewModel()
{
}
}
I'm curious about the cause of this problem and possible solutions.
Thank you for the clarification. I reproduced this issue and researched it.
I found that BooleanToVisibilityConverter itself does not cause the issue. When I copy its implementation to a sample project, the result is similar to the standard converter. It occurs due to extra code executed when DevExpress components are used, and you'll see the same behavior if you use, for example, SimpleButton from our suite. However, the most interesting thing is that it's very easy to reproduce this behavior without DevExpress at all - for this you need to subscribe to the Loaded event for a control within a window. Please take a look at the modified sample where I demonstrated this.
Further research shows that this happens due to the SubtreeHasLoadedChangeHandler property value check in the IsLoaded getter - this is the specificity we cannot control at the level of our components.
Since there is no connection between IsLoaded and IsVisible properties in a general case, I recommend you re-work your current solution to make it more reliable. For example:
Show LoginView as a modal window to make sure that MainWindow is created after LoginView is closed;
var loginView = new LoginView();
loginView.ShowDialog();
var mainView = new MainWindow();
mainView.Show();
Handle the Closing/Closed event for LoginView instead of IsVisibleChanged. Thanks
문제 원인