В моем приложении wpf есть usercontrol, который вызывает исключение stackoverflow, когда оно создается более одного раза. Я попытался отладить причину исключения, и оно возникло во время InitializeComponent моего Usercontrol. Когда я вхожу в InitializeComponent, он переходит на код приложения app.xaml.cs и считывает значения, содержащиеся в классе «Настройки».
Я "новичок" в использовании настроек приложения C #, поэтому раньше я не сталкивался с этой ошибкой. Не уверен, является ли это обычным делом или нет при работе с ними. Кроме того, это единственный пользовательский контроль в настоящее время в моем приложении, который позволяет изменять переменные настроек, и это единственный пользовательский контроль, который демонстрирует такое поведение.
Я думаю, что моя проблема как-то связана с классом DebugOptions, использующим текст данных «Application.Current», и затем я создаю другой экземпляр с тем же текстом данных, но как только я получаю доступ к любому из его свойств, я начинаю путать приложение какой объект есть какой. Хотя это имеет смысл в моей голове, логически это не сработает, потому что этот пользовательский контроль запускается при нажатии кнопки, а его панель хоста очищается перед добавлением, чтобы предотвратить вращение нескольких экземпляров.
Ниже приведены xaml и код моего управления пользователями. Он не имеет зависимостей, кроме свойств CLR из класса App, с которым он связан. Я бы хотел, чтобы у меня было больше информации по этому вопросу, но это очень странное исключение, которое появляется.
Вот свойство в моем классе приложения, которое вызывает исключение stackoverflow при обращении к нему «Get».
private Byte _debuglevel = Merlin.Properties.Settings.Default.DebugLevel;
public Byte DebugLevel
{
get { return _debuglevel; }
set { _debuglevel = value; }
}
public partial class DebugOptions : UserControl
{
public DebugOptions()
{
InitializeComponent();
}
private void ChangeLogDirectoryButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
MessageBox.Show("Make a decision here...choose to use the old winforms folder browser control or find one on the web because the std openfiledialog can't be overriden to select folders only.", "Fix this..");
}
private void UpdateDebugOptionsButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
//update debug level
Merlin.Properties.Settings.Default.DebugLevel = (Byte)DebugLevelSlider.Value;
//update log boolean
if ((bool)EnableLoggingRadioButton.IsChecked)
{
Merlin.Properties.Settings.Default.LogsEnabled = true;
}
else
{
Merlin.Properties.Settings.Default.LogsEnabled = false;
}
//update log path?
//save "settings"
Merlin.Properties.Settings.Default.Save();
//write a log event noting changes
App myappreference = (App)Application.Current;
Merlin.Helper.logger.pLogToFile(string.Format("Log Settings Updated at {0} by {1}", DateTime.Now.ToString(), myappreference.CurrentUser.UserName));
}
private void OpenLogDirectoryButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
Process process = new Process();
Process.Start("Explorer.exe", Merlin.Properties.Settings.Default.LogsDirectory);
}
}
Ресурсы UserControl и теги UserControl для краткости опущены
<Border BorderBrush="Black" BorderThickness="1" Margin="0">
<Grid DataContext="{Binding Source={x:Static Application.Current}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Content="Debug Options" HorizontalAlignment="Center" Margin="0" Grid.Row="0" VerticalAlignment="Center" FontSize="29.333" Style="{StaticResource UserControlTitleLabelStyle}" />
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Label Content="Set Debug Level" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Slider x:Name="DebugLevelSlider" HorizontalAlignment="Left" VerticalAlignment="Center" Maximum="10" Value="{Binding DebugLevel}" Minimum="1" Margin="62,0,0,0" TickPlacement="BottomRight" SmallChange="1" Style="{StaticResource SliderStyle1}" Width="119">
<Slider.ToolTip>
<ToolTip Content="{Binding DebugLevel}" ContentStringFormat="{}The current value is {0} out of 10"/>
</Slider.ToolTip>
</Slider>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="2">
<Label Content="Application Level Logging: " />
<RadioButton x:Name="EnableLoggingRadioButton" GroupName="Logs" Content="Enable" Margin="5" IsChecked="{Binding LogsEnabled}">
<RadioButton.ToolTip>
<TextBlock Text="Selecting this option will enable logs at the debug level selected above."/>
</RadioButton.ToolTip>
</RadioButton>
<RadioButton x:Name="DisableLoggingRadioButton" GroupName="Logs" Content="Disable" Margin="5" IsChecked="{Binding Path=IsChecked,ElementName=EnableLoggingRadioButton, Converter={StaticResource oppositebooleanconverter}}" >
<RadioButton.ToolTip>
<TextBlock Text="Selecting this option will disable all logs for the application."/>
</RadioButton.ToolTip>
</RadioButton>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="3">
<Label Content="Log Path" HorizontalAlignment="Left" VerticalAlignment="Center" />
<TextBox Margin="10" Width="347.553" TextWrapping="Wrap" Text="{Binding LogsDirectory}" VerticalAlignment="Stretch" />
<StackPanel Height="100">
<Button x:Name="OpenLogDirectoryButton" Content="Open Directory" Width="100" Margin="0,10,0,0" VerticalAlignment="Center" HorizontalAlignment="Right" Style="{StaticResource ButtonStyle}" d:LayoutOverrides="GridBox" Click="OpenLogDirectoryButton_Click" />
<Button x:Name="ChangeLogDirectoryButton" Content="Change Directory" Width="100" Margin="0,10,0,0" VerticalAlignment="Center" HorizontalAlignment="Right" Style="{StaticResource ButtonStyle}" d:LayoutOverrides="GridBox" Click="ChangeLogDirectoryButton_Click" IsEnabled="False" />
</StackPanel>
</StackPanel>
<Button x:Name="UpdateDebugOptionsButton" Content="Update" Grid.Row="4" Width="100" VerticalAlignment="Center" HorizontalAlignment="Right" Style="{StaticResource ButtonStyle}" Click="UpdateDebugOptionsButton_Click" Margin="0,0,8,10" />
</Grid>
</Border>
Stacktrace ДО создания исключения
Merlin.exe! Merlin.App.LogsEnabled.set (значение bool = false) Строка 52 C #
[Внешний код]
Merlin.exe! Merlin.View.DebugOptions.DebugOptions () Строка 25 + 0x8 байт C #
[Внешний код]
Merlin.exe! Merlin.View.TestView.TestView () Строка 24 + 0x8 байт C #
Merlin.exe! Merlin.MainWindow.SidebarButtonsClickHandler (object sender = {Merlin.ImageButton}, System.Windows.RoutedEventArgs e = {System.Windows.RoutedEventArgs}) Строка 218 + 0x15 байт C #
[Внешний код]
Странно, что во время процедуры initializecomponent получается логическое значение LogsEnabled, а затем сразу же вызывается для его установки. Я понятия не имею, что вызывает это, чтобы установить это. Но как только он устанавливает значение, он пытается получить его снова. Я уверен, что среда выполнения выбрасывает стековый поток, чтобы предотвратить бесконечный цикл. Так как я могу понять, почему он хочет это сделать?