Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当opacity属性发生更改并随后发生等待方法调用时,UI不会更新_C#_Windows Phone 8_Windows Phone_Async Await - Fatal编程技术网

C# 当opacity属性发生更改并随后发生等待方法调用时,UI不会更新

C# 当opacity属性发生更改并随后发生等待方法调用时,UI不会更新,c#,windows-phone-8,windows-phone,async-await,C#,Windows Phone 8,Windows Phone,Async Await,当我的应用程序启动时,它会调用一个方法来显示进度指示器。此方法将内容区域的不透明度设置为0,将进度条的不透明度设置为1。这是一个弹出控件 进度指示器的弹出式xaml: <Popup x:Name="loadingOverlay" IsOpen="{Binding IsProgressBarOpen}" Margin="10,-100,0,0" Opacity="{Binding OpacityProgre

当我的应用程序启动时,它会调用一个方法来显示进度指示器。此方法将内容区域的不透明度设置为0,将进度条的不透明度设置为1。这是一个弹出控件

进度指示器的弹出式xaml:

        <Popup 
        x:Name="loadingOverlay" 
        IsOpen="{Binding IsProgressBarOpen}"
        Margin="10,-100,0,0" 
        Opacity="{Binding OpacityProgressBar}"
        VerticalAlignment="Center" HorizontalAlignment="Center">
        <Border 
            x:Name="loadingOverlayPanel"   
            BorderBrush="{StaticResource PhoneAccentBrush}" >
            <StackPanel 
                VerticalAlignment="Center">
                <telerik:RadBusyIndicator 
                    x:Name="LoadingVisualAngleTransform" 
                    Content=" "
                    Foreground="{Binding ActiveTheme.ForegroundAlt1, Source={StaticResource ThemeController}}"
                    FontSize="18"
                    FontWeight="Bold"
                    IndicatorAnimationStyle="{StaticResource ColorWheelIndicatorAnimation}"
                    IsRunning="True"
                    Opacity="{Binding OpacityProgressBar}"
                    VerticalAlignment="Center">
                </telerik:RadBusyIndicator>
            </StackPanel>
        </Border>
    </Popup>
我遇到的问题是,如果showProgressBar方法调用后面跟着wait方法调用,则进度指示器没有显示

在下面的代码中,我首先调用进度条显示,然后请求获取手机的位置坐标。接下来的代码应该只在收到坐标后运行,这就是我使用wait关键字的原因。我假设showProgressBar和setLocationCoordinates调用之间的短时间没有给UI足够的更新时间?奇怪的是,在调试时,一旦获取了位置坐标,我注意到进度指示器仍然没有出现

                // Progress bar should be shown as weather is being fetched.
                App.ViewModel.showProgressBar();

                // Must retrieve GPS location details with the status of
                // the requested recorded into a variable.
                // Have 3 attemps cause sometimes first attempt fails.
                string status = "";
                int attempts = 1;
                while( status != "success" )
                {
                    status = await App.ViewModel.GPS.setLocationCoordinates();

                    if (status == "success")
                    {
                        App.ViewModel.GPS.setLocationDetails();
                        break;
                    }

                    attempts++;
                    if (attempts > 3)
                        break;
                }
我应该补充一点,如果showProgressBar后面没有wait方法,则不会出现此问题

更新:在我的页面中添加了xaml,以向Pantelis表明我实际上一直在使用他的推荐。我有一个没有不透明度绑定的网格,弹出控件和轴控件作为兄弟控件,每个控件都绑定了不透明度。如果这不是你的建议,请告诉我

    <!-- RESOURCES -->
<phone:PhoneApplicationPage.Resources>

    <Style x:Key="ColorWheelIndicatorAnimation" TargetType="telerikBusy:BusyIndicatorAnimation">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <StackPanel
                        x:Name="PART_LayoutRoot">
                        <StackPanel.Resources>
                            <Storyboard 
                                x:Name="PART_Animation" 
                                RepeatBehavior="Forever">
                                <DoubleAnimation
                                    Storyboard.TargetName="progressBarIcon1"
                                    Storyboard.TargetProperty="Opacity"
                                    From="1.0" To="0.0" Duration="0:0:1"
                                    AutoReverse="True"/>
                                <DoubleAnimation
                                    Storyboard.TargetName="progressBarIcon2"
                                    Storyboard.TargetProperty="Opacity"
                                    From="0.0" To="1.0" Duration="0:0:1"
                                    AutoReverse="True"/>
                            </Storyboard>
                        </StackPanel.Resources>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <TextBlock 
                                Grid.Row="0"
                                x:Name="progressBarIcon1" 
                                FontSize="48"
                                FontFamily="/Assets/Fonts/WeatherIcons-Regular.otf#Weather Icons" 
                                Foreground="{Binding ActiveTheme.Foreground, Source={StaticResource ThemeController}}"
                                Text="&#xf055;" 
                                HorizontalAlignment="Center" 
                                VerticalAlignment="Center"/>
                            <TextBlock Grid.Row="0"
                                x:Name="progressBarIcon2" 
                                FontSize="48"
                                FontFamily="/Assets/Fonts/WeatherIcons-Regular.otf#Weather Icons" 
                                Foreground="{Binding ActiveTheme.Foreground, Source={StaticResource ThemeController}}"
                                Text="&#xf053;" 
                                HorizontalAlignment="Center" 
                                VerticalAlignment="Center"/>
                        </Grid>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</phone:PhoneApplicationPage.Resources>



<!--LAYOUT CONTAINER -->
<Grid 
    x:Name="LayoutRoot" 
    Background="{Binding ActiveTheme.Background, Source={StaticResource ThemeController}}"
    CacheMode="BitmapCache">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" MinHeight="800"/>
    </Grid.RowDefinitions>


    <!-- LOADING OVERLAY -->
    <Popup 
        x:Name="loadingOverlay" 
        IsOpen="{Binding IsProgressBarOpen}"
        Margin="10,-100,0,0" 
        Opacity="{Binding OpacityProgressBar}"
        VerticalAlignment="Center" HorizontalAlignment="Center">
        <Border 
            x:Name="loadingOverlayPanel"   
            BorderBrush="{StaticResource PhoneAccentBrush}" >
            <StackPanel 
                VerticalAlignment="Center">
                <telerik:RadBusyIndicator 
                    x:Name="LoadingVisualAngleTransform" 
                    Content=" "
                    Foreground="{Binding ActiveTheme.ForegroundAlt1, Source={StaticResource ThemeController}}"
                    FontSize="18"
                    FontWeight="Bold"
                    IndicatorAnimationStyle="{StaticResource ColorWheelIndicatorAnimation}"
                    IsRunning="True"
                    Opacity="{Binding OpacityProgressBar}"
                    VerticalAlignment="Center">
                </telerik:RadBusyIndicator>
            </StackPanel>
        </Border>
    </Popup>


    <!-- TITLE BAR START -->
    <StackPanel 
        Grid.Row="0" 
        Margin="0,17,0,0"
        Opacity="{Binding OpacityContent}"
        x:Name="titleBar">

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="70" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="50"/>
            </Grid.ColumnDefinitions>


            <TextBlock 
                FontWeight="Bold"
                FontSize="18"
                Foreground="{Binding ActiveTheme.ForegroundAlt1, Source={StaticResource ThemeController}}" 
                Grid.Row="0"
                Grid.Column="1"
                Margin="0,0,0,0"
                Opacity="0.5"
                Tap="Title_Tap" 
                Text="title"/>
        </Grid>
    </StackPanel>
    <!-- TITLE BAR END -->

    <!-- PIVOTS -->
    <!-- Taken from: http://social.msdn.microsoft.com/Forums/wpapps/en-us/1baf74fa-0ddd-4226-a02d-a7fc9f80374d/pivot-static-header-like-twitter-app?forum=wpdevelop-->
    <controls:Pivot
        x:Name="MainPivot"
        Background="{Binding ActiveTheme.Background, Source={StaticResource ThemeController}}"
        Foreground="{Binding ActiveTheme.Foreground, Source={StaticResource ThemeController}}"
        Margin="0,50,0,0" 
        Opacity="{Binding OpacityContent}"
        Padding="0,0,0,0"
        SelectionChanged="Pivot_SelectionChanged">

        // Pivots defined here, but none of them use OpacityContent
    </controls:Pivot>

</Grid>
更新2:以下是在调用showProgressBar方法后调用的异步方法:

    public async Task<string> setLocationCoordinates()
    {
        // Get the latitude and longitude.
        status = await this.setCoordinates();
        if (status == "success")
        {
            this.CoordinatesFetched = true;
        }
        this.CoordinatesFetched = false;

        return status;
    }


    public async Task<string> setCoordinates()
    {
        // Need to initialise the tracking mechanism. 
        Geolocator geolocator = new Geolocator();

        // Must determine if GPS is on/off.
        if (geolocator.LocationStatus == PositionStatus.Disabled)
        {
            Status = false;
            // If off, get out.
            return "gps off";
        }
        else
            Status = true;

        // Setup the desired accuracy in meters for data returned from the location service.
        geolocator.DesiredAccuracyInMeters = 50;

        try
        {
            // Taken from: http://bernhardelbl.wordpress.com/2013/11/26/geolocator-getgeopositionasync-with-correct-timeout/
            // Because sometimes GetGeopositionAsync does not return. So you need to add a timeout procedure by your self.

            // get the async task
            var asyncResult = geolocator.GetGeopositionAsync();
            var task = asyncResult.AsTask();

            // add a race condition - task vs timeout task
            var readyTask = await Task.WhenAny(task, Task.Delay(10000));
            if (readyTask != task) // timeout wins
            {
                return "error";
                //throw new TimeoutException();
            }

            // position found within timeout
            Geoposition geoposition = await task;

            // Retrieve latitude and longitude.
            Latitude = Convert.ToDouble(geoposition.Coordinate.Latitude.ToString("0.0000000000000"));
            Longitude = Convert.ToDouble(geoposition.Coordinate.Longitude.ToString("0.0000000000000"));

            // Update the 'Current Location' db record.
            var query = from LocationDbRecord location in App.ViewModel.LocationDb.Locations
                        where location.LocationId == 1
                        select location;

            foreach (LocationDbRecord l in query)
            {
                l.Latitude = Latitude.ToString();
                l.Longitude = Longitude.ToString();
            }

            // Submit the changes to the database. 
            try
            {
                App.ViewModel.LocationDb.SubmitChanges();
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee);
            }

            return "success";
        }
        // If there's an error, may be because the ID_CAP_LOCATION in the app manifest wasn't include. 
        // Alternatively, may be because the user hasn't turned on the Location Services.
        catch (Exception ex)
        {
            if ((uint)ex.HResult == 0x80004004)
            {
                return "gps off";
            }
            else
            {
                // Something else happened during the acquisition of the location.
                // Return generic error message.
                return "error";
            }
        }
    }
这是在获取坐标后调用的方法,以获取位置的名称:

    public void setLocationDetails()
    {
        // Must perform reverse geocoding i.e. get location from latitude/longitude.
        ReverseGeocodeQuery query = new ReverseGeocodeQuery()
            {
                GeoCoordinate = new GeoCoordinate(Latitude, Longitude)
            };
        query.QueryCompleted += query_QueryCompleted;
        query.QueryAsync();
    }

    /**
     * Event called when the reverse geocode call returns a location result.
     **/
    void query_QueryCompleted(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
    {
        foreach (var item in e.Result)
        {
            Location = item.Information.Address.City;

            // Update the 'Current Location' db record.
            var query = from LocationDbRecord location in App.ViewModel.LocationDb.Locations
                        where location.LocationId == 1
                        select location;

            foreach (LocationDbRecord l in query)
            {
                l.Country = "Somewhere in " + Location;
            }

            // Submit the changes to the database. 
            try
            {
                App.ViewModel.LocationDb.SubmitChanges();
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee);
            }

            // Need to passively update the current location's general location in the locations Db.
            this.updateCurrentLocationLiveTileDbRecord(item.Information.Address.City, item.Information.Address.Country, item.GeoCoordinate.Latitude, item.GeoCoordinate.Longitude);
            return;
        }
    }

这是因为任何嵌套元素的不透明度都是由它们所包含的元素继承的。您必须在单个单元格网格中获得弹出窗口和stackpanel(繁忙指示器所在的位置),以停止不透明度继承

<Grid>
    <Popup Opacity="{Binding ...}"/>
    <ProgressBar Opacity="{Binding ...}"/>
</Grid>

尝试将setLocationCoordinates方法更改为:

public Task<string> setLocationCoordinates() {
    return Task.Run(async delegate() {
        // Get the latitude and longitude.
        status = await this.setCoordinates();
        this.CoordinatesFetched = status == "success";
        return status;
    });
}
当我编辑这段代码时,我注意到您总是将CoordinationsFetched设置为false。这是有意的吗?还是我错过了什么?在我的代码中,它取决于status的值


另外,正如@Pantelis所说的,只要有可能,你应该使用可见性而不是不透明度来显示/隐藏控件,这大约是99%的情况。

好的,所以我通过添加以下内容来实现这一点:

this.loadingOverlay.IsOpen=true

调用setLocationCoordinates之前,然后在调用之后手动将其设置为false,因为showProgressBar中的this.IsProgressBarOpen=false行似乎没有更新它。出于我现在正在研究的某些原因,正在加载Overlay的IsOpen属性。如果有人知道原因,请告诉我,因为我很好奇


谢谢大家的建议和建议。我会考虑的。

您是否尝试过单步调试SetLocationCoordinates方法以查看是否返回?放置等待任务。在showProgressBar之后立即屈服,并查看发生了什么。是的,SetLocationCoordinates方法工作正常,并且在获取坐标后正确返回成功。发生的情况是,只有一个空白屏幕,然后突然出现天气,即OpacityContent变为1。我添加了等待任务。showProgressBar之后立即放弃,但不幸的是,这似乎没有任何区别。异步方法的代码是什么?如果这个方法不是真正的异步的,它会导致这种行为。原来的帖子现在用相关的xaml更新了。如果我错了或者我误解了你的建议,请纠正我。我不确定我是否完全理解你的布局逻辑。在获取位置数据时,您正在显示忙指示器。完成后,您希望向UI的其余部分显示一个神秘的标题栏,其中有4列,只有一个子项和pivot控件。对吗?您是否尝试过更改控件的可见性属性?这是在UI上显示/隐藏元素的首选方式。同样像@yasen提到的,异步方法的实现是什么?我想IsProgressBarOpen是可以观察到的?也就是说,它要么是DependencyProperty,要么在设置时从INotifyPropertyChanged接口引发PropertyChanged事件?它是可观察的,是的。
public Task<string> setLocationCoordinates() {
    return Task.Run(async delegate() {
        // Get the latitude and longitude.
        status = await this.setCoordinates();
        this.CoordinatesFetched = status == "success";
        return status;
    });
}